mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 22:03:42 -07:00
commit
d8984626db
273 changed files with 29981 additions and 9303 deletions
14
.github/ISSUE_TEMPLATE/checklist-for-release.md
vendored
14
.github/ISSUE_TEMPLATE/checklist-for-release.md
vendored
|
@ -22,14 +22,14 @@ assignees: doegox, iceman1001
|
||||||
# OS compilation and tests
|
# OS compilation and tests
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make clean && make -j PLATFORM=PM3OTHER && tools/pm3test.sh
|
make clean && make -j PLATFORM=PM3OTHER && tools/pm3_tests.sh
|
||||||
make clean && make -j PLATFORM=PM3RDV4 && tools/pm3test.sh
|
make clean && make -j PLATFORM=PM3RDV4 && tools/pm3_tests.sh
|
||||||
make clean && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON && tools/pm3test.sh
|
make clean && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON && tools/pm3_tests.sh
|
||||||
make install; pushd /tmp; proxmark3 -c 'data load em4x05.pm3;lf search 1'; popd; make uninstall
|
make install; pushd /tmp; proxmark3 -c 'data load -f em4x05.pm3;lf search 1'; popd; make uninstall
|
||||||
|
|
||||||
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3OTHER && PM3BIN=./proxmark3 ../../tools/pm3test.sh client )
|
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3OTHER && PM3BIN=./proxmark3 ../../tools/pm3_tests.sh client )
|
||||||
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3RDV4 && PM3BIN=./proxmark3 ../../tools/pm3test.sh client )
|
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3RDV4 && PM3BIN=./proxmark3 ../../tools/pm3_tests.sh client )
|
||||||
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON && PM3BIN=./proxmark3 ../../tools/pm3test.sh client )
|
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON && PM3BIN=./proxmark3 ../../tools/pm3_tests.sh client )
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] RPI Zero
|
- [ ] RPI Zero
|
||||||
|
|
133
.github/workflows/macos.yml
vendored
Normal file
133
.github/workflows/macos.yml
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
name: MacOS Build and Test
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
macos-make:
|
||||||
|
runs-on: macos-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set Git http.postBuffer to something high
|
||||||
|
run: git config --global http.postBuffer 524288000
|
||||||
|
|
||||||
|
- name: Handle homebrew quirks
|
||||||
|
run: rm -rf /usr/local/bin/2to3
|
||||||
|
|
||||||
|
- name: Update brew repos
|
||||||
|
run: brew update
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Tap RfidResearchGroup/proxmark3
|
||||||
|
run: brew tap RfidResearchGroup/proxmark3
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: brew install readline qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
python3 -m pip install setuptools ansicolors sslcrypto
|
||||||
|
if [ -f requirements.txt ]; then python3 -m pip install -r requirements.txt; fi
|
||||||
|
|
||||||
|
- name: make clean
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
env:
|
||||||
|
V: 1
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
macos-make-btaddon:
|
||||||
|
if: always()
|
||||||
|
needs: [macos-make]
|
||||||
|
runs-on: macos-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set Git http.postBuffer to something high
|
||||||
|
run: git config --global http.postBuffer 524288000
|
||||||
|
|
||||||
|
- name: Handle homebrew quirks
|
||||||
|
run: rm -rf /usr/local/bin/2to3
|
||||||
|
|
||||||
|
- name: Update brew repos
|
||||||
|
run: brew update
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Tap RfidResearchGroup/proxmark3
|
||||||
|
run: brew tap RfidResearchGroup/proxmark3
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: brew install readline qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
python3 -m pip install setuptools ansicolors sslcrypto
|
||||||
|
if [ -f requirements.txt ]; then python3 -m pip install -r requirements.txt; fi
|
||||||
|
|
||||||
|
- name: make clean
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
env:
|
||||||
|
V: 1
|
||||||
|
PLATFORM_EXTRAS: BTADDON
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
macos-cmake:
|
||||||
|
if: always()
|
||||||
|
needs: [macos-make, macos-make-btaddon]
|
||||||
|
runs-on: macos-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set Git http.postBuffer to something high
|
||||||
|
run: git config --global http.postBuffer 524288000
|
||||||
|
|
||||||
|
- name: Handle homebrew quirks
|
||||||
|
run: rm -rf /usr/local/bin/2to3
|
||||||
|
|
||||||
|
- name: Update brew repos
|
||||||
|
run: brew update
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Tap RfidResearchGroup/proxmark3
|
||||||
|
run: brew tap RfidResearchGroup/proxmark3
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: brew install readline qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
python3 -m pip install setuptools ansicolors sslcrypto
|
||||||
|
if [ -f requirements.txt ]; then python3 -m pip install -r requirements.txt; fi
|
||||||
|
|
||||||
|
- name: Prepare Build Folders
|
||||||
|
run: mkdir -p client/build
|
||||||
|
|
||||||
|
- name: Initiate cmake environment
|
||||||
|
run: cmake ..
|
||||||
|
working-directory: client/build/
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
env:
|
||||||
|
VERBOSE: 1
|
||||||
|
run: make
|
||||||
|
working-directory: client/build/
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
env:
|
||||||
|
CHECKARGS: "--clientbin ./client/build/proxmark3"
|
||||||
|
run: make client/check
|
106
.github/workflows/ubuntu.yml
vendored
Normal file
106
.github/workflows/ubuntu.yml
vendored
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
name: Ubuntu Build and Test
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ubuntu-make:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Update apt repos
|
||||||
|
run: sudo apt-get update
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
python3 -m pip install setuptools
|
||||||
|
python3 -m pip install ansicolors sslcrypto
|
||||||
|
if [ -f requirements.txt ]; then python3 -m pip install -r requirements.txt; fi
|
||||||
|
|
||||||
|
- name: make clean
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
env:
|
||||||
|
V: 1
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
ubuntu-make-btaddon:
|
||||||
|
if: always()
|
||||||
|
needs: [ubuntu-make]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Update apt repos
|
||||||
|
run: sudo apt-get update
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
python3 -m pip install setuptools
|
||||||
|
python3 -m pip install ansicolors sslcrypto
|
||||||
|
if [ -f requirements.txt ]; then python3 -m pip install -r requirements.txt; fi
|
||||||
|
|
||||||
|
- name: make clean
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
env:
|
||||||
|
V: 1
|
||||||
|
PLATFORM_EXTRAS: BTADDON
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
ubuntu-cmake:
|
||||||
|
if: always()
|
||||||
|
needs: [ubuntu-make, ubuntu-make-btaddon]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Update apt repos
|
||||||
|
run: sudo apt-get update
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
python3 -m pip install setuptools
|
||||||
|
python3 -m pip install ansicolors sslcrypto
|
||||||
|
if [ -f requirements.txt ]; then python3 -m pip install -r requirements.txt; fi
|
||||||
|
|
||||||
|
- name: Prepare Build Folders
|
||||||
|
run: mkdir -p client/build
|
||||||
|
|
||||||
|
- name: Initiate cmake environment
|
||||||
|
run: cmake ..
|
||||||
|
working-directory: client/build/
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
env:
|
||||||
|
VERBOSE: 1
|
||||||
|
run: make
|
||||||
|
working-directory: client/build/
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
env:
|
||||||
|
CHECKARGS: "--clientbin ./client/build/proxmark3"
|
||||||
|
run: make client/check
|
152
.github/workflows/windows.yml
vendored
Normal file
152
.github/workflows/windows.yml
vendored
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
name: Windows Build and Test
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
proxspace:
|
||||||
|
runs-on: windows-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: pwsh
|
||||||
|
env:
|
||||||
|
PATH: C:/ProxSpace/msys2/mingw64/bin;C:/ProxSpace/msys2/usr/local/bin;C:/ProxSpace/msys2/usr/bin;C:/ProxSpace/msys2/bin
|
||||||
|
MSYSTEM: MINGW64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: ProxSpace download
|
||||||
|
run: Invoke-WebRequest "https://github.com/Gator96100/ProxSpace/archive/master.zip" -outfile "C:\proxspace.zip" -Passthru
|
||||||
|
|
||||||
|
- name: ProxSpace extract
|
||||||
|
run: Expand-Archive -LiteralPath "C:\proxspace.zip" -DestinationPath "C:\"
|
||||||
|
|
||||||
|
- name: ProxSpace delete zip
|
||||||
|
run: Remove-Item "C:\proxspace.zip"
|
||||||
|
|
||||||
|
- name: ProxSpace rename folder
|
||||||
|
run: Get-ChildItem -Path "C:\ProxSpace-*" | Rename-Item -NewName (Split-Path C:\ProxSpace -Leaf)
|
||||||
|
|
||||||
|
- name: ProxSpace version
|
||||||
|
run: |
|
||||||
|
$psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "C:\ProxSpace\msys2\ps\09-proxspace_setup.post").Line.Split("""")[1]
|
||||||
|
Write-Host "ProxSpace version: $psversion"
|
||||||
|
|
||||||
|
- name: ProxSpace initial startup
|
||||||
|
working-directory: C:\ProxSpace
|
||||||
|
run: ./runme64.bat -c "exit"
|
||||||
|
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: make clean
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: make V=1
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
- name: make clean
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Build btaddon
|
||||||
|
run: make V=1 PLATFORM_EXTRAS=BTADDON
|
||||||
|
|
||||||
|
- name: Test btaddon
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
- name: make clean
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Prepare cmake build folders
|
||||||
|
run: mkdir -p client/build
|
||||||
|
|
||||||
|
- name: Initiate cmake environment
|
||||||
|
run: cmake -G"MSYS Makefiles" ..
|
||||||
|
working-directory: client/build/
|
||||||
|
|
||||||
|
- name: Build cmake
|
||||||
|
run: make VERBOSE=1
|
||||||
|
working-directory: client/build/
|
||||||
|
|
||||||
|
- name: Test cmake
|
||||||
|
run: make client/check CHECKARGS="--clientbin ./client/build/proxmark3"
|
||||||
|
|
||||||
|
wsl:
|
||||||
|
runs-on: windows-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: wsl-bash {0}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: WSL setup
|
||||||
|
uses: Vampire/setup-wsl@v1
|
||||||
|
with:
|
||||||
|
distribution: Ubuntu-20.04
|
||||||
|
update: "true"
|
||||||
|
additional-packages: git
|
||||||
|
ca-certificates
|
||||||
|
build-essential
|
||||||
|
pkg-config
|
||||||
|
libreadline-dev
|
||||||
|
gcc-arm-none-eabi
|
||||||
|
libnewlib-dev
|
||||||
|
libbz2-dev
|
||||||
|
qtbase5-dev
|
||||||
|
cmake
|
||||||
|
libpython3-dev
|
||||||
|
python3
|
||||||
|
python3-pip
|
||||||
|
python3-dev
|
||||||
|
libpython3-all-dev
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
python3 -m pip install setuptools
|
||||||
|
python3 -m pip install ansicolors sslcrypto
|
||||||
|
|
||||||
|
- name: WSL QT fix
|
||||||
|
run: sudo strip --remove-section=.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
|
||||||
|
|
||||||
|
- name: Set git to use LF
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git config --global core.autocrlf false
|
||||||
|
git config --global core.eol lf
|
||||||
|
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: make clean
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: make V=1
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
- name: make clean
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Build btaddon
|
||||||
|
run: make V=1 PLATFORM_EXTRAS=BTADDON
|
||||||
|
|
||||||
|
- name: Test btaddon
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
- name: make clean
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Prepare cmake build folders
|
||||||
|
run: mkdir -p client/build
|
||||||
|
|
||||||
|
- name: Initiate cmake environment
|
||||||
|
run: cmake ..
|
||||||
|
working-directory: client/build/
|
||||||
|
|
||||||
|
- name: Build cmake
|
||||||
|
run: make VERBOSE=1
|
||||||
|
working-directory: client/build/
|
||||||
|
|
||||||
|
- name: Test cmake
|
||||||
|
run: make client/check CHECKARGS="--clientbin ./client/build/proxmark3"
|
13
.gitignore
vendored
13
.gitignore
vendored
|
@ -33,6 +33,7 @@ version.c
|
||||||
*.json.bak
|
*.json.bak
|
||||||
*.pyc
|
*.pyc
|
||||||
*.bmp
|
*.bmp
|
||||||
|
originalitysig.csv
|
||||||
|
|
||||||
# new build file for add-ons.
|
# new build file for add-ons.
|
||||||
Makefile.platform
|
Makefile.platform
|
||||||
|
@ -71,6 +72,7 @@ tools/cryptorf/cm
|
||||||
tools/cryptorf/sm
|
tools/cryptorf/sm
|
||||||
tools/cryptorf/sma
|
tools/cryptorf/sma
|
||||||
tools/cryptorf/sma_multi
|
tools/cryptorf/sma_multi
|
||||||
|
tools/mf_nonce_brute/mf_nonce_brute
|
||||||
|
|
||||||
fpga/*
|
fpga/*
|
||||||
!fpga/tests
|
!fpga/tests
|
||||||
|
@ -93,18 +95,21 @@ client/traces/*
|
||||||
client/dumps/*
|
client/dumps/*
|
||||||
*.ice
|
*.ice
|
||||||
*.new
|
*.new
|
||||||
tools/mf_nonce_brute/mf_nonce_brute
|
|
||||||
tools/andrew/*
|
|
||||||
tools/jtag_openocd/openocd_configuration
|
|
||||||
ppls patches/*
|
|
||||||
*- Copy.*
|
*- Copy.*
|
||||||
|
/EF_*
|
||||||
|
|
||||||
client/lualibs/mfc_default_keys.lua
|
client/lualibs/mfc_default_keys.lua
|
||||||
client/lualibs/pm3_cmd.lua
|
client/lualibs/pm3_cmd.lua
|
||||||
# recompiled
|
# recompiled
|
||||||
fpga_version_info.c
|
fpga_version_info.c
|
||||||
|
|
||||||
|
# log / history
|
||||||
.proxmark3/*
|
.proxmark3/*
|
||||||
|
|
||||||
# .tmp files are created during compilation
|
# .tmp files are created during compilation
|
||||||
*.tmp
|
*.tmp
|
||||||
|
|
||||||
|
# VSCode files
|
||||||
|
!.vscode/templates/*.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
|
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=827846
|
||||||
|
// for the documentation about the extensions.json format
|
||||||
|
"recommendations": [
|
||||||
|
"ms-vscode.cpptools",
|
||||||
|
"austin.code-gnu-global",
|
||||||
|
"marus25.cortex-debug",
|
||||||
|
"augustocdias.tasks-shell-input"
|
||||||
|
]
|
||||||
|
}
|
145
.vscode/setup.sh
vendored
Executable file
145
.vscode/setup.sh
vendored
Executable file
|
@ -0,0 +1,145 @@
|
||||||
|
#!/bin/bash
|
||||||
|
###############################
|
||||||
|
# Linux #
|
||||||
|
# Uncomment to override #
|
||||||
|
###############################
|
||||||
|
#export SerialPort="/dev/ttyACM0"
|
||||||
|
#export DebuggerPath="/usr/bin/gdb"
|
||||||
|
#export JLinkServerPath="/opt/SEGGER/JLink/JLinkGDBServerCLExe"
|
||||||
|
|
||||||
|
###############################
|
||||||
|
# WSL #
|
||||||
|
# Uncomment to override #
|
||||||
|
###############################
|
||||||
|
#export SerialPort="/dev/ttyS4"
|
||||||
|
#export DebuggerPath="/usr/bin/gdb"
|
||||||
|
#export JLinkServerPath="/mnt/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe"
|
||||||
|
|
||||||
|
###############################
|
||||||
|
# ProxSpace #
|
||||||
|
# Uncomment to override #
|
||||||
|
###############################
|
||||||
|
#export SerialPort="COM5"
|
||||||
|
#export JLinkServerPath="C:/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe"
|
||||||
|
|
||||||
|
#Debugging on 256KB systems is not recommended
|
||||||
|
#This option does not override PLATFORM_SIZE
|
||||||
|
export DeviceMem="512"
|
||||||
|
|
||||||
|
|
||||||
|
VSCODEPATH=$(dirname "$0")
|
||||||
|
|
||||||
|
function print_config {
|
||||||
|
echo "Updating with following configuration:"
|
||||||
|
echo "SerialPort: $SerialPort"
|
||||||
|
echo "DebuggerPath: $DebuggerPath"
|
||||||
|
echo "JLinkServerPath: $JLinkServerPath"
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_serial_port {
|
||||||
|
if [ -z "$SerialPort" ]; then
|
||||||
|
pm3list=$($VSCODEPATH/../pm3 --list 2>/dev/null)
|
||||||
|
#Use first port listed
|
||||||
|
export SerialPort=$(echo $pm3list | head -n 1 | cut -c 4-)
|
||||||
|
if [ -z "$SerialPort" ]; then
|
||||||
|
echo >&2 "[!!] No serial port found, please set SerialPort manually"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_gdb_linux {
|
||||||
|
if [ -z "$DebuggerPath" ]; then
|
||||||
|
export DebuggerPath="/usr/bin/gdb"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$DebuggerPath" ]; then
|
||||||
|
echo >&2 "[!!] gdb not found, please set DebuggerPath manually"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_jlink_linux {
|
||||||
|
if [ -z "$JLinkServerPath" ]; then
|
||||||
|
export JLinkServerPath="/opt/SEGGER/JLink/JLinkGDBServerCLExe"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JLinkServerPath" ]; then
|
||||||
|
echo >&2 "[!!] JLinkGDBServerCLExe not found, please set JLinkServerPath manually"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_jlink_wsl {
|
||||||
|
if [ -z "$JLinkServerPath" ]; then
|
||||||
|
export JLinkServerPath="/mnt/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JLinkServerPath" ]; then
|
||||||
|
echo >&2 "[!!] JLinkGDBServerCL.exe not found, please set JLinkServerPath manually"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_jlink_ps {
|
||||||
|
if [ -z "$JLinkServerPath" ]; then
|
||||||
|
export JLinkServerPath="c:/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe"
|
||||||
|
fi
|
||||||
|
jlinkpath=$(cygpath "$JLinkServerPath")
|
||||||
|
if [ ! -x "$jlinkpath" ]; then
|
||||||
|
echo >&2 "[!!] JLinkGDBServerCL.exe not found, please set JLinkServerPath manually"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_wsl {
|
||||||
|
setup_serial_port
|
||||||
|
setup_gdb_linux
|
||||||
|
setup_jlink_wsl
|
||||||
|
print_config
|
||||||
|
envsubst '${SerialPort} ${DebuggerPath} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_wsl.json" > "$VSCODEPATH/launch.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_linux {
|
||||||
|
setup_serial_port
|
||||||
|
setup_gdb_linux
|
||||||
|
setup_jlink_linux
|
||||||
|
print_config
|
||||||
|
envsubst '${SerialPort} ${DebuggerPath} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_linux.json" > "$VSCODEPATH/launch.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_ps {
|
||||||
|
setup_serial_port
|
||||||
|
setup_jlink_ps
|
||||||
|
export DebuggerPath="Using ProxSpace gbd"
|
||||||
|
print_config
|
||||||
|
envsubst '${SerialPort} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_ps.json" > "$VSCODEPATH/launch.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -f "$VSCODEPATH/launch.json" ]; then
|
||||||
|
read -p "Existing configuration found, do you want to override it? " -n 1 -r
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]
|
||||||
|
then
|
||||||
|
rm "$VSCODEPATH/launch.json.bak" 2> /dev/null
|
||||||
|
mv "$VSCODEPATH/launch.json" "$VSCODEPATH/launch.json.bak" 2> /dev/null
|
||||||
|
else
|
||||||
|
echo >&2 "[!!] user abort"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
HOSTOS=$(uname | awk '{print toupper($0)}')
|
||||||
|
if [ "$HOSTOS" = "LINUX" ]; then
|
||||||
|
if uname -a|grep -q Microsoft; then
|
||||||
|
setup_wsl
|
||||||
|
else
|
||||||
|
setup_linux
|
||||||
|
fi
|
||||||
|
elif [ "$HOSTOS" = "DARWIN" ]; then
|
||||||
|
echo >&2 "[!!] MacOS not supported, sorry!"
|
||||||
|
exit 1
|
||||||
|
elif [[ "$HOSTOS" =~ MINGW(32|64)_NT* ]]; then
|
||||||
|
setup_ps
|
||||||
|
else
|
||||||
|
echo >&2 "[!!] Host OS not recognized, abort: $HOSTOS"
|
||||||
|
exit 1
|
||||||
|
fi
|
101
.vscode/tasks.json
vendored
101
.vscode/tasks.json
vendored
|
@ -2,23 +2,20 @@
|
||||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
// for the documentation about the tasks.json format
|
// for the documentation about the tasks.json format
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
|
"windows": {
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"env": {
|
||||||
|
"PATH": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin",
|
||||||
|
"MSYSTEM": "MINGW64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"label": "all: Make & run",
|
"label": "all: Make & run",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "make -j && ./pm3",
|
"command": "make -j && ./pm3",
|
||||||
"windows": {
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/../..",
|
|
||||||
"shell": {
|
|
||||||
"executable": "${workspaceFolder}/../../runme64.bat",
|
|
||||||
"args": [
|
|
||||||
"-c \"cd ${workspaceFolderBasename} &&"
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$gcc"
|
"$gcc"
|
||||||
],
|
],
|
||||||
|
@ -31,18 +28,6 @@
|
||||||
"label": "choose: Make",
|
"label": "choose: Make",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "make ${input:componentType} -j",
|
"command": "make ${input:componentType} -j",
|
||||||
"windows": {
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/../..",
|
|
||||||
"shell": {
|
|
||||||
"executable": "${workspaceFolder}/../../runme64.bat",
|
|
||||||
"args": [
|
|
||||||
"-c \"cd ${workspaceFolderBasename} &&"
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$gcc"
|
"$gcc"
|
||||||
],
|
],
|
||||||
|
@ -52,18 +37,6 @@
|
||||||
"label": "client: Debug: make",
|
"label": "client: Debug: make",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "make client -j DEBUG=1",
|
"command": "make client -j DEBUG=1",
|
||||||
"windows": {
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/../..",
|
|
||||||
"shell": {
|
|
||||||
"executable": "${workspaceFolder}/../../runme64.bat",
|
|
||||||
"args": [
|
|
||||||
"-c \"cd ${workspaceFolderBasename} &&"
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$gcc"
|
"$gcc"
|
||||||
],
|
],
|
||||||
|
@ -73,18 +46,6 @@
|
||||||
"label": "client: Debug: clean & make",
|
"label": "client: Debug: clean & make",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "make client/clean && make client -j DEBUG=1",
|
"command": "make client/clean && make client -j DEBUG=1",
|
||||||
"windows": {
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/../..",
|
|
||||||
"shell": {
|
|
||||||
"executable": "${workspaceFolder}/../../runme64.bat",
|
|
||||||
"args": [
|
|
||||||
"-c \"cd ${workspaceFolderBasename} &&"
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$gcc"
|
"$gcc"
|
||||||
],
|
],
|
||||||
|
@ -94,55 +55,27 @@
|
||||||
"label": "fullimage: Make & Flash",
|
"label": "fullimage: Make & Flash",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "make fullimage && ./pm3-flash-fullimage",
|
"command": "make fullimage && ./pm3-flash-fullimage",
|
||||||
"windows": {
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/../..",
|
|
||||||
"shell": {
|
|
||||||
"executable": "${workspaceFolder}/../../runme64.bat",
|
|
||||||
"args": [
|
|
||||||
"-c \"cd ${workspaceFolderBasename} &&"
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "BOOTROM: Make & Flash",
|
"label": "BOOTROM: Make & Flash",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "make bootrom && ./pm3-flash-bootrom",
|
"command": "make bootrom && ./pm3-flash-bootrom",
|
||||||
"windows": {
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/../..",
|
|
||||||
"shell": {
|
|
||||||
"executable": "${workspaceFolder}/../../runme64.bat",
|
|
||||||
"args": [
|
|
||||||
"-c \"cd ${workspaceFolderBasename} &&"
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Run client",
|
"label": "Run client",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "./pm3",
|
"command": "./pm3",
|
||||||
"windows": {
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/../..",
|
|
||||||
"shell": {
|
|
||||||
"executable": "${workspaceFolder}/../../runme64.bat",
|
|
||||||
"args": [
|
|
||||||
"-c \"cd ${workspaceFolderBasename} &&"
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
|
},{
|
||||||
|
"label": "fullimage: clean & make debug",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make armsrc/clean && make armsrc/all DEBUG_ARM=1",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"inputs": [
|
"inputs": [
|
||||||
|
|
|
@ -5,34 +5,11 @@
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "(gdb) Attach",
|
"name": "Client: (gdb) Build & Launch",
|
||||||
"type": "cppdbg",
|
|
||||||
"request": "attach",
|
|
||||||
"program": "${cwd}/client/proxmark3",
|
|
||||||
//"processId": "${command:pickProcess}",
|
|
||||||
"processId": "${input:ProcessID}",
|
|
||||||
"MIMode": "gdb",
|
|
||||||
"setupCommands": [
|
|
||||||
{
|
|
||||||
"description": "Enable pretty-printing for gdb",
|
|
||||||
"text": "-enable-pretty-printing",
|
|
||||||
"ignoreFailures": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"windows": {
|
|
||||||
"processId": "${input:ProcessIDWindows}",
|
|
||||||
"miDebuggerPath": "${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe",
|
|
||||||
"externalConsole": true,//for ProxSpace externalConsole=true is required, because the internal cosole stops updating after a while
|
|
||||||
"environment": [{
|
|
||||||
"name": "PATH","value": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
},{
|
|
||||||
"name": "(gdb) Build & Launch",
|
|
||||||
"type": "cppdbg",
|
"type": "cppdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${cwd}/client/proxmark3",
|
"program": "${cwd}/client/proxmark3",
|
||||||
"args": ["/dev/ttyACM0"],
|
"args": ["${SerialPort}"],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"environment": [],
|
"environment": [],
|
||||||
|
@ -46,15 +23,36 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"preLaunchTask": "client: Debug: clean & make",
|
"preLaunchTask": "client: Debug: clean & make",
|
||||||
"miDebuggerPath": "/usr/bin/gdb",
|
"miDebuggerPath": "${DebuggerPath}"
|
||||||
"windows": {
|
},{
|
||||||
"args": ["COM5"],
|
"name": "Client: (gdb) Attach",
|
||||||
"miDebuggerPath": "${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe",
|
"type": "cppdbg",
|
||||||
"externalConsole": true,//for ProxSpace externalConsole=true is required, because the internal cosole stops updating after a while
|
"request": "attach",
|
||||||
"environment": [{
|
"program": "${cwd}/client/proxmark3",
|
||||||
"name": "PATH","value": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin"
|
//"processId": "${command:pickProcess}",
|
||||||
}]
|
"processId": "${input:ProcessID}",
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "Enable pretty-printing for gdb",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
},{
|
||||||
|
"name": "Firmware: (J-Link) Build & Launch",
|
||||||
|
"type": "cortex-debug",
|
||||||
|
"request": "launch",
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"preLaunchTask": "fullimage: clean & make debug",
|
||||||
|
"executable": "${workspaceRoot}/armsrc/obj/fullimage.elf",
|
||||||
|
"serverpath": "${JLinkServerPath}",
|
||||||
|
"servertype": "jlink",
|
||||||
|
"device": "AT91SAM7S${DeviceMem}",
|
||||||
|
"interface": "jtag",
|
||||||
|
"serialNumber": "", //If you have more than one J-Link probe, add the serial number here.
|
||||||
|
"runToMain": false,
|
||||||
|
"armToolchainPath": "/usr/bin/"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"inputs": [
|
"inputs": [
|
||||||
|
@ -67,14 +65,6 @@
|
||||||
"command": "pgrep -n proxmark3",
|
"command": "pgrep -n proxmark3",
|
||||||
}
|
}
|
||||||
|
|
||||||
},{
|
|
||||||
"id": "ProcessIDWindows",
|
|
||||||
"type": "command",
|
|
||||||
"command": "shellCommand.execute",
|
|
||||||
"args": {
|
|
||||||
"command": "${workspaceFolder}/../../runme64.bat -c \"cat /proc/$(pgrep -n proxmark3)/winpid\"",
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
49
.vscode/templates/launch_ps.json
vendored
Normal file
49
.vscode/templates/launch_ps.json
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"env": {
|
||||||
|
"PATH": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin",
|
||||||
|
"MSYSTEM": "MINGW64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Client: (gdb) Build & Launch",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"program": "${cwd}/client/proxmark3",
|
||||||
|
"args": ["${SerialPort}"],
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"externalConsole": true,//for ProxSpace externalConsole=true is required, because the internal cosole stops updating after a while
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "Enable pretty-printing for gdb",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preLaunchTask": "client: Debug: clean & make",
|
||||||
|
"miDebuggerPath": "${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe"
|
||||||
|
},{
|
||||||
|
"name": "Firmware: (J-Link) Build & Launch",
|
||||||
|
"type": "cortex-debug",
|
||||||
|
"request": "launch",
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"preLaunchTask": "fullimage: clean & make debug",
|
||||||
|
"executable": "${workspaceRoot}/armsrc/obj/fullimage.elf",
|
||||||
|
"serverpath": "${JLinkServerPath}",
|
||||||
|
"servertype": "jlink",
|
||||||
|
"device": "AT91SAM7S${DeviceMem}",
|
||||||
|
"interface": "jtag",
|
||||||
|
"serialNumber": "", //If you have more than one J-Link probe, add the serial number here.
|
||||||
|
"runToMain": false,
|
||||||
|
"armToolchainPath": "${workspaceFolder}/../../msys2/mingw64/bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
70
.vscode/templates/launch_wsl.json
vendored
Normal file
70
.vscode/templates/launch_wsl.json
vendored
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Client: (gdb) Build & Launch",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${cwd}/client/proxmark3",
|
||||||
|
"args": ["${SerialPort}"],
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"environment": [],
|
||||||
|
"externalConsole": false,
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "Enable pretty-printing for gdb",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preLaunchTask": "client: Debug: clean & make",
|
||||||
|
"miDebuggerPath": "${DebuggerPath}"
|
||||||
|
},{
|
||||||
|
"name": "Client: (gdb) Attach",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "attach",
|
||||||
|
"program": "${cwd}/client/proxmark3",
|
||||||
|
//"processId": "${command:pickProcess}",
|
||||||
|
"processId": "${input:ProcessID}",
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "Enable pretty-printing for gdb",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},{
|
||||||
|
"name": "Firmware: (J-Link) Build & Launch",
|
||||||
|
"type": "cortex-debug",
|
||||||
|
"request": "launch",
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"preLaunchTask": "fullimage: clean & make debug",
|
||||||
|
"executable": "${workspaceRoot}/armsrc/obj/fullimage.elf",
|
||||||
|
"serverpath": "${JLinkServerPath}",
|
||||||
|
"servertype": "jlink",
|
||||||
|
"device": "AT91SAM7S${DeviceMem}",
|
||||||
|
"interface": "jtag",
|
||||||
|
"serialNumber": "", //If you have more than one J-Link probe, add the serial number here.
|
||||||
|
"runToMain": false,
|
||||||
|
"armToolchainPath": "/usr/bin/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
// Using Extension "Tasks Shell Input" https://marketplace.visualstudio.com/items?itemName=augustocdias.tasks-shell-input
|
||||||
|
"id": "ProcessID",
|
||||||
|
"type": "command",
|
||||||
|
"command": "shellCommand.execute",
|
||||||
|
"args": {
|
||||||
|
"command": "pgrep -n proxmark3",
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
76
CHANGELOG.md
76
CHANGELOG.md
|
@ -3,29 +3,67 @@ All notable changes to this project will be documented in this file.
|
||||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
- Added a script to dump originality signatures from MFU EV1s and NTAGs (@aveao)
|
||||||
|
- Added parsing of EF_CardAccess to display PACE algorithm, version and parameter in `hf emrtd info` (@aveao)
|
||||||
|
- Change, numerous commands more uses cliparser (@tcprst, @iceman1001)
|
||||||
|
- Added more originality public keys (@anon)
|
||||||
|
- Added `hf 14a info` - now also verify MFC Ev1 signatures (@iceman1001)
|
||||||
|
- Added `LF_THAREXDE` standalone mode which simulates and reads EM4x50 cards (@tharexde)
|
||||||
|
- Added `hf jooki` commands (@iceman1001)
|
||||||
|
- Changed `lf hid clone` - also accepts binary wiegand (@iceman1001)
|
||||||
|
- Changed `wiegand encode` - format param is now optional, w/o it will try encode all formats (@iceman1001)
|
||||||
|
- Fix cppchecker warnings (@iceman1001)
|
||||||
|
- Added `trace list -t mf` - now can use external dictionary keys file (@McEloff)
|
||||||
|
- Fix `lf gallagher read` - now correctly decodes card data
|
||||||
|
- Add support to `lf gallagher clone` and `lf gallagher sim` for writing specific card region, facility, card & issue numbers (@DarkMatterMatt)
|
||||||
|
- Added support for older vid/pid detection (@Gator96100)
|
||||||
|
- Added `hf mfdes bruteaid` - proper bruteforce of DESFire AID when no reading of files is possible (@craftbyte)
|
||||||
|
- Added support for bidirectional communication for `lf em 4x50 sim` (@tharexde)
|
||||||
|
- Change `PLATFORM=PM3OTHER` to `PLATFORM=PM3GENERIC` (@iceman1001)
|
||||||
|
- Added `tools/hitag2crack/crack5opencl`, an optimized version of `crack5gpu` (@matrix)
|
||||||
|
- Fixed Makefile to account for changes when running on Apple Silicon (@tcprst)
|
||||||
|
- Added support for debugging ARM with JTAG & VSCode (@Gator96100)
|
||||||
|
- Added MFUL "Gen1b" suport to `hf_mfu_setuid.lua` (@iceman1001)
|
||||||
|
- Added possibility to get bargraph in `lf tune` and `hf tune` (@iceman1001, @doegox)
|
||||||
|
- Added `hf emrtd` ePassport dumping and parsing (@aveao)
|
||||||
|
- Added `aidsearch` to `hf 14b info` (@iceman1001)
|
||||||
|
- Added `ICE_STATE_DUMP_SIM` - standalone mode for dumping/simming one iClass tag (@iconicsec)
|
||||||
|
- Added `lf em 4x50 eview` - show uploaded EM4x50 data in emul memory (@tharexde)
|
||||||
|
- Fix `data rawdemod` parsing for psk2 and user defined clock (@cyberpunk-re)
|
||||||
|
- Added `hf iclass encode` - encode a wiegand binary to a encrypted credential (@iceman1001)
|
||||||
|
- Changed `recoverpk.py` - now tests more ECDSA curves (@doegox)
|
||||||
|
- Added `hf 14a apdufuzz`- a naive apdu cla/ins/p1p2/len fuzzer (@iceman1001)
|
||||||
|
- Improved `hf 14a apdufuzz/apdufind` to find hidden APDUs (@ikarus23)
|
||||||
|
- Fix mixed up INC/DEC in MIFARE protocol defs (@vortixdev)
|
||||||
|
- Added `lf em 4x70 info` - new support for ID48 transponders (@cmolson)
|
||||||
|
- Fix multiple coverity scan issues (@iceman1001)
|
||||||
|
- Added a SIO item (@iceman1001)
|
||||||
|
- Fix `lf hid brute` - param (@iceman1001)
|
||||||
|
- Changed `lf em` layouts (@iceman1001)
|
||||||
|
- Change many commands to cliparser (@iceman1001, @tcprst, ...)
|
||||||
- Fix issue #844 - `lf t55xx config` => recompute block0 (@cyberpunk-re)
|
- Fix issue #844 - `lf t55xx config` => recompute block0 (@cyberpunk-re)
|
||||||
- EM4x50: changed cli parameter from w (word) to d (data) (@tharexde)
|
- Change `lf em 4x50` - changed cli parameter from w (word) to d (data) (@tharexde)
|
||||||
- EM4x50: new function 4x50 login: authenticate against tag (@tharexde)
|
- Added `lf em 4x50 login` - authenticate against tag (@tharexde)
|
||||||
- EM4x50: new function 4x50 brute: guess password within a given password range (@tharexde)
|
- Added `lf em 4x50 brute` - guess password within a given password range (@tharexde)
|
||||||
- EM4x50: new function 4x50 chk: try passwords from dictionary (without option -> T55xx default dictionary or -f user dictionary) (@tharexde)
|
- Added `lf em 4x50 chk` - try passwords from dictionary (without option -> T55xx default dictionary or -f user dictionary) (@tharexde)
|
||||||
- EM4x50: new function 4x50 reader: read data from tag (configured data -> standard read mode), incl. option -@ (@tharexde)
|
- Added `lf em 4x50 reader` - read data from tag (configured data -> standard read mode), incl. option -@ (@tharexde)
|
||||||
- EM4x50: new function 4x50 sim: simulate dump from file or emulator/flash (@tharexde)
|
- Added `lf em 4x50 sim` - simulate dump from file or emulator/flash (@tharexde)
|
||||||
- EM4x50: new function 4x50 restore: restore dump file (bin, eml, json) onto tag (@tharexde)
|
- Added `lf em 4x50 restore` - restore dump file (bin, eml, json) onto tag (@tharexde)
|
||||||
- EM4x50: new function 4x50 esave: dump em4x50 content in emulator memory to file (bin + eml + json) (@tharexde)
|
- Added `lf em 4x50 esave` - dump em4x50 content in emulator memory to file (bin + eml + json) (@tharexde)
|
||||||
- EM4x50: new function 4x50 eload: upload em4x50 file content (bin, eml, json) to emulator memory (@tharexde)
|
- Added `lf em 4x50 eload` - upload em4x50 file content (bin, eml, json) to emulator memory (@tharexde)
|
||||||
- EM4x50: added LED signals (@tharexde)
|
- Changed EM4x50 - added LED signals (@tharexde)
|
||||||
- EM4x50: added json format for 4x50 dump (@tharexde)
|
- Change `lf em 4x50 dump` - now support json format (@tharexde)
|
||||||
- EM4x50: relocated write requests in function 4x50 wipe from device to client (@tharexde)
|
- Change `lf em 4x50 wipe` - relocated write requests from device to client (@tharexde)
|
||||||
- EM4x50: renamed 4x50_write_password to 4x50 writepwd (@tharexde)
|
- Renamed `lf em 4x50 write_passwordd` -> `writepwd` (@tharexde)
|
||||||
- EM4x50: all hex input parameters now have to be given in lsb format (output is still msb + lsb) (@tharexde)
|
- Change `lf em 4x50` - all hex input parameters now have to be given in lsb format (output is still msb + lsb) (@tharexde)
|
||||||
- EM4x50: changed cli parameter from a (address) to b (block) (@tharexde)
|
- Change `lf em 4x50` - changed cli parameter from a (address) to b (block) (@tharexde)
|
||||||
- EM4x50: switched to cliparser for all functions (@tharexde)
|
- Change `lf em 4x50` - now supports cliparser (@tharexde)
|
||||||
- EM4x50: stabilized and accelerated tag detection (@tharexde)
|
- Change EM4x50 - stabilized and accelerated tag detection (@tharexde)
|
||||||
- EM4x50: removed global tag structure on device side (@tharexde)
|
- Change EM4x50 - removed global tag structure on device side (@tharexde)
|
||||||
- Fix `hf 15 sim` - Added basic response to GET_SYSTEM_INFO and READBLOCK requests in order to fix iso15693 tag sim (@cyberpunk-re)
|
- Fix `hf 15 sim` - Added basic response to GET_SYSTEM_INFO and READBLOCK requests in order to fix iso15693 tag sim (@cyberpunk-re)
|
||||||
- Added `mf mfu sim t 7 n <numreads>` - MFU emulation now supports automatic exit after <num> blocks read. (@cyberpunk-re)
|
- Added `mf mfu sim t 7 n <numreads>` - MFU emulation now supports automatic exit after <num> blocks read. (@cyberpunk-re)
|
||||||
- Added T55xx Guide to assist in learning how to use the T55xx chip (@mwalker33)
|
- Added T55xx Guide to assist in learning how to use the T55xx chip (@mwalker33)
|
||||||
- Fix 'hf iclass wrbl' - dealing with tags in unsecured vs secured pagemode now is correct (@iceman1001)
|
- Fix `hf iclass wrbl` - dealing with tags in unsecured vs secured pagemode now is correct (@iceman1001)
|
||||||
- Change many commands to cliparser (@iceman1001, @tcprst, @mwalker33,...)
|
- Change many commands to cliparser (@iceman1001, @tcprst, @mwalker33,...)
|
||||||
- ...
|
- ...
|
||||||
- Change `hf iclass chk/lookup/loclass` speedups (@iceman1001)
|
- Change `hf iclass chk/lookup/loclass` speedups (@iceman1001)
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -46,7 +46,7 @@ ifneq (,$(INSTALLTOOLS))
|
||||||
endif
|
endif
|
||||||
ifneq (,$(INSTALLSIMFW))
|
ifneq (,$(INSTALLSIMFW))
|
||||||
$(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
|
$(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
|
||||||
$(Q)$(CP) $(foreach fw,$(INSTALLSIMFW),tools/simmodule/$(fw)) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
|
$(Q)$(CP) $(foreach fw,$(INSTALLSIMFW),client/resources/$(fw)) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLFWRELPATH)
|
||||||
endif
|
endif
|
||||||
ifeq ($(platform),Linux)
|
ifeq ($(platform),Linux)
|
||||||
$(Q)$(MKDIR) $(DESTDIR)$(UDEV_PREFIX)
|
$(Q)$(MKDIR) $(DESTDIR)$(UDEV_PREFIX)
|
||||||
|
@ -169,7 +169,7 @@ help:
|
||||||
@echo "+ fpga_compress - Make tools/fpga_compress"
|
@echo "+ fpga_compress - Make tools/fpga_compress"
|
||||||
@echo
|
@echo
|
||||||
@echo "+ style - Apply some automated source code formatting rules"
|
@echo "+ style - Apply some automated source code formatting rules"
|
||||||
@echo "+ cliparser - Generate cliparser TODO
|
@echo "+ cliparser - Generate cliparser TODO"
|
||||||
@echo "+ check - Run offline tests. Set CHECKARGS to pass arguments to the test script"
|
@echo "+ check - Run offline tests. Set CHECKARGS to pass arguments to the test script"
|
||||||
@echo "+ .../check - Run offline tests against specific target. See above."
|
@echo "+ .../check - Run offline tests against specific target. See above."
|
||||||
@echo "+ miscchecks - Detect various encoding issues in source code"
|
@echo "+ miscchecks - Detect various encoding issues in source code"
|
||||||
|
|
|
@ -57,6 +57,11 @@ else
|
||||||
RANLIB= ranlib
|
RANLIB= ranlib
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# For detection of Apple Silicon
|
||||||
|
ifeq ($(platform),Darwin)
|
||||||
|
BREW_PREFIX = $(shell brew --prefix)
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(DEBUG),1)
|
ifeq ($(DEBUG),1)
|
||||||
DEFCXXFLAGS = -g -O0 -pipe
|
DEFCXXFLAGS = -g -O0 -pipe
|
||||||
DEFCFLAGS = -g -O0 -fstrict-aliasing -pipe
|
DEFCFLAGS = -g -O0 -fstrict-aliasing -pipe
|
||||||
|
@ -66,6 +71,11 @@ else
|
||||||
DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe
|
DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe
|
||||||
DEFLDFLAGS =
|
DEFLDFLAGS =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(DEBUG_ARM),1)
|
||||||
|
APP_CFLAGS += -g
|
||||||
|
SKIP_COMPRESSION=1
|
||||||
|
endif
|
||||||
# Next ones are activated only if SANITIZE=1
|
# Next ones are activated only if SANITIZE=1
|
||||||
ifeq ($(SANITIZE),1)
|
ifeq ($(SANITIZE),1)
|
||||||
DEFCFLAGS += -g -fsanitize=address -fno-omit-frame-pointer
|
DEFCFLAGS += -g -fsanitize=address -fno-omit-frame-pointer
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Run 'make PLATFORM=' to get an exhaustive list of possible parameters for this file.
|
# Run 'make PLATFORM=' to get an exhaustive list of possible parameters for this file.
|
||||||
|
|
||||||
PLATFORM=PM3RDV4
|
PLATFORM=PM3RDV4
|
||||||
#PLATFORM=PM3OTHER
|
#PLATFORM=PM3GENERIC
|
||||||
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
|
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
|
||||||
#PLATFORM_EXTRAS=BTADDON
|
#PLATFORM_EXTRAS=BTADDON
|
||||||
#STANDALONE=HF_MSDSAL
|
#STANDALONE=HF_MSDSAL
|
||||||
|
|
109
README.md
109
README.md
|
@ -1,15 +1,18 @@
|
||||||
# RRG / Iceman repo - Proxmark3
|
# RRG / Iceman - Proxmark3
|
||||||
|
|
||||||
|
|
||||||
|
| Releases | Coverity | Contributors |
|
||||||
|
| ------------------- | -------------------:| -------------------:|
|
||||||
|
| [](https://github.com/RfidResearchGroup/proxmark3/releases/latest) | [](https://scan.coverity.com/projects/proxmark3-rrg-iceman-repo)|  |
|
||||||
|
|
||||||
|
|
||||||
|
| Actions OSX CI | Actions Ubuntu CI | Windows CI |
|
||||||
|
| ------------------- | -------------------:| -------------------:|
|
||||||
|
|  |  | [](https://ci.appveyor.com/project/RfidResearchGroup/proxmark3/branch/master) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# PROXMARK3 INSTALLATION AND OVERVIEW
|
||||||
| Releases | Linux & OSX CI | Windows CI | Coverity | Contributors |
|
|
||||||
| ------------------- |:-------------------:| -------------------:| -------------------:| -------------------:|
|
|
||||||
| [](https://github.com/RfidResearchGroup/proxmark3/releases/latest) | [](https://travis-ci.com/RfidResearchGroup/proxmark3) | [](https://ci.appveyor.com/project/RfidResearchGroup/proxmark3/branch/master) | [](https://scan.coverity.com/projects/proxmark3-rrg-iceman-repo)|  |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# PROXMARK INSTALLATION AND OVERVIEW
|
|
||||||
|
|
||||||
| FAQ's & Updates | Installation | Use of the Proxmark |
|
| FAQ's & Updates | Installation | Use of the Proxmark |
|
||||||
| ------------------- |:-------------------:| -------------------:|
|
| ------------------- |:-------------------:| -------------------:|
|
||||||
|
@ -36,10 +39,25 @@
|
||||||
|[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)|
|
|[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)|
|
||||||
|[Notes on cliparser usage](/doc/cliparser.md)|[Notes on clocks](/doc/clocks.md)||
|
|[Notes on cliparser usage](/doc/cliparser.md)|[Notes on clocks](/doc/clocks.md)||
|
||||||
|
|
||||||
## 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)
|
## Build for Proxmark3 RDV4
|
||||||
|
See the instruction links in the tables above to build, flash and run for your Proxmark3 RDV4 device.
|
||||||
|
|
||||||
|
## Build for generic Proxmark3 platforms
|
||||||
|
In order to build this repo for generic Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)
|
||||||
|
|
||||||
|
With generic Proxmark3 platforms we mean:
|
||||||
|
- RDV1
|
||||||
|
- RDV2
|
||||||
|
- RDV3 easy
|
||||||
|
- Proxmark Evolution (needs extra care)
|
||||||
|
- Radiowar black PCB version
|
||||||
|
- Ryscorp green PCB version
|
||||||
|
- Ryscorp Pm3Pro
|
||||||
|
- VX
|
||||||
|
- numerous Chinese adapted versions of the RDV3 easy (kkmoon, pisworks etc)
|
||||||
|
|
||||||
|
> ⚠ **Note**: About flash memory size of other Proxmark3 platforms. You need to keep a eye on how large your ARM chip built-in flash memory is. With 512kb you are fine but if its 256kb you need to compile this repo with even less functionality. When running the `./pm3-flash-all` you can see which size your device have if you have the bootloader from this repo installed. Otherwise you will find the size reported in the start message when running the Proxmark3 client `./pm3`.
|
||||||
|
|
||||||
## What has changed?
|
## What has changed?
|
||||||
|
|
||||||
|
@ -49,7 +67,9 @@ On the hardware side:
|
||||||
* added smart card module
|
* added smart card module
|
||||||
* added FPC connector
|
* added FPC connector
|
||||||
|
|
||||||
On the software side: quite a lot, see the [Changelog file](CHANGELOG.md).
|
On the software side:
|
||||||
|
|
||||||
|
quite a lot, see the [Changelog file](CHANGELOG.md) which we try to keep updated.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
@ -57,13 +77,13 @@ On the software side: quite a lot, see the [Changelog file](CHANGELOG.md).
|
||||||
|
|
||||||
This repo compiles nicely on
|
This repo compiles nicely on
|
||||||
- Proxspace v3.x
|
- Proxspace v3.x
|
||||||
- [latest release v3.7.1](https://github.com/Gator96100/ProxSpace/releases)
|
- [latest release v3.8](https://github.com/Gator96100/ProxSpace/releases)
|
||||||
- Windows/mingw environment with Qt5.6.1 & GCC 4.9
|
- Windows/mingw environment with Qt5.6.1 & GCC 4.9
|
||||||
- Ubuntu 16.04 -> 20.04
|
- Ubuntu 16.04 -> 20.04
|
||||||
- ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian
|
- ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian
|
||||||
- Rasbian
|
- Rasbian
|
||||||
- Android / Termux
|
- Android / Termux
|
||||||
- Mac OS X / Homebrew
|
- Mac OS X / Homebrew / Apple Silicon
|
||||||
- WSL1 (Windows subsystem linux) on Windows 10
|
- WSL1 (Windows subsystem linux) on Windows 10
|
||||||
- Docker container
|
- Docker container
|
||||||
- [ RRG / Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3)
|
- [ RRG / Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3)
|
||||||
|
@ -72,26 +92,22 @@ This repo compiles nicely on
|
||||||
Hardware to run client on
|
Hardware to run client on
|
||||||
- PC
|
- PC
|
||||||
- Android
|
- Android
|
||||||
- Raspberry Pi & Raspberry Pi Zero
|
- Raspberry Pi, Raspberry Pi Zero
|
||||||
- Nvidia Jetson Nano
|
- Nvidia Jetson Nano
|
||||||
|
|
||||||
## Precompiled binaries
|
## Precompiled binaries
|
||||||
We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where @gator96100 has set up a google drive with many mingw binaries which is up-to-date. We link to these files here as to make it easier for users.
|
We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which is recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users.
|
||||||
If you are having troubles with these files, contact the package maintainer @gator96100 and read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) where known issues has been documented.
|
|
||||||
|
|
||||||
|
_If you use his pre-compiled Proxspace binaries do consider buy him a coffee for his efforts. Remember nothing says thank you as good as a donation._
|
||||||
|
|
||||||
Ref:
|
If you are having troubles with these files, contact the package maintainer [@gator96100](https://github.com/gator96100) and read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) where known issues has been documented with regards to the precompiled builds.
|
||||||
For Proxmark3 RDV4
|
|
||||||
- [Precompiled builds for RDV40 dedicated x86](https://drive.google.com/open?id=13zUs-aiQkYaSl5KWrBtuW5IWCoHJPsue)
|
|
||||||
- [Precompiled builds for RDV40 dedicated x64](https://drive.google.com/open?id=1SyPB8t5Vo8O0Lh7PjNm3Kv-mO4BNbxjX)
|
|
||||||
|
|
||||||
For Proxmark3 RDV4 with blueshark addon
|
### Proxmark3 RDV4 devices
|
||||||
- [Precompiled builds for RDV40 dedicated with Bluetooth addon x86](https://drive.google.com/open?id=1TqWYctkRvkLshQ1ZRBHPLDzYHR-asuMO)
|
- [Precompiled builds for RDV40 dedicated x64](https://www.proxmarkbuilds.org/#rdv40-64/)
|
||||||
- [Precompiled builds for RDV40 dedicated with Bluetooth addon x64](https://drive.google.com/open?id=17ful7u2QyYmMQzQzc5fAf8nJvyoDJfSL)
|
- [Precompiled builds for RDV40 dedicated with Bluetooth addon x64](https://www.proxmarkbuilds.org/#rdv40_bt-64/)
|
||||||
|
|
||||||
Generice Proxmark3 devices (non RDV4), for Proxmark3 Easy, RDV1, RDV2, RDV3, etc etc
|
### Generic Proxmark3 devices
|
||||||
- [Precompiled builds for RRG / Iceman repository x86](https://drive.google.com/open?id=1PI3Xr1mussPBPnYGu4ZjWzGPARK4N7JR)
|
- [Precompiled builds for RRG / Iceman repository x64](https://www.proxmarkbuilds.org/#rrg_other-64/)
|
||||||
- [Precompiled builds for RRG / Iceman repository x64](https://drive.google.com/open?id=1uX9RtYGinuFrpHybu4xq_BE3HrobI20e)
|
|
||||||
|
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
@ -103,28 +119,40 @@ We usually merge your contributions fast since we do like the idea of getting a
|
||||||
|
|
||||||
## Issues & Troubleshooting
|
## Issues & Troubleshooting
|
||||||
Please search the [issues](https://github.com/rfidresearchgroup/proxmark3/issues) page here and see if your issue is listed in the first instance.
|
Please search the [issues](https://github.com/rfidresearchgroup/proxmark3/issues) page here and see if your issue is listed in the first instance.
|
||||||
Read the [Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md) guide to weed out most known problems.
|
Read the [Troubleshooting guide](/doc/md/Installation_Instructions/Troubleshooting.md) to weed out most known problems.
|
||||||
|
|
||||||
Next place to visit is the [Proxmark Forum](http://www.proxmark.org/forum/index.php). Learn to search it well and finally Google / duckduckgo is your friend :) You will find many blogposts, youtube videos, tweets, reddit
|
Next place to visit is the [Proxmark3 Forum](http://www.proxmark.org/forum/index.php). Learn to search it well and finally Google / duckduckgo is your friend :)
|
||||||
|
You will find many blogposts, youtube videos, tweets, reddit
|
||||||
|
|
||||||
### Offical channels
|
### Offical channels
|
||||||
|
- [RFID Hacking community discord server](https://discord.gg/QfPvGFRQxH)
|
||||||
- [Proxmark3 IRC channel](http://webchat.freenode.net/?channels=#proxmark3)
|
- [Proxmark3 IRC channel](http://webchat.freenode.net/?channels=#proxmark3)
|
||||||
- [Proxmark3 sub reddit](https://www.reddit.com/r/proxmark3/)
|
- [Proxmark3 sub reddit](https://www.reddit.com/r/proxmark3/)
|
||||||
- [Twitter](https://twitter.com/proxmark3/)
|
- [Proxmark3 Twitter](https://twitter.com/proxmark3/)
|
||||||
- [Proxmark3 community discord server](https://discord.gg/zjxc8ZB)
|
- [Proxmark3 forum](http://www.proxmark.org/forum/index.php)
|
||||||
|
- _no slack channel_
|
||||||
|
|
||||||
_no slack channel_
|
|
||||||
|
|
||||||
Iceman has quite a few videos on his [youtube channel](https://www.youtube.com/c/ChrisHerrmann1001)
|
### Youtube channels
|
||||||
|
Iceman has quite a few videos on his channel and Quentyn has risen up the last year with good informative videos. We suggest you check them out and smash that subscribe buttons!
|
||||||
|
|
||||||
|
- [Iceman channel](https://www.youtube.com/c/ChrisHerrmann1001)
|
||||||
|
- [Quentyn Taylor](https://www.youtube.com/channel/UCL91C3IZDv3wfj2ABhdRIrw)
|
||||||
|
- [Hacker warehouse channel](https://www.youtube.com/channel/UCimS6P854cQ23j6c_xst7EQ)
|
||||||
|
|
||||||
|
_if you think of some more good youtube channels to be on this list, let us know!_
|
||||||
|
|
||||||
## Cheat sheet
|
## Cheat sheet
|
||||||
|
|
||||||
Thanks to Alex Dibs, you can enjoy a [command cheat sheet](/doc/cheatsheet.md)
|
You can enjoy a [command cheat sheet](/doc/cheatsheet.md) and we are trying to keep it updated.
|
||||||
|
[Thanks to Alex Dib!](https://github.com/scund00r)
|
||||||
|
|
||||||
## Maintainers ( package, distro )
|
## 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.
|
To all distro, package maintainers, we tried to make your life easier.
|
||||||
- [Maintainers](/doc/md/Development/Maintainers.md)
|
|
||||||
|
`make install` is now available and if you want to know more.
|
||||||
|
- [Notes for maintainers](/doc/md/Development/Maintainers.md)
|
||||||
|
|
||||||
## Why didn't you base it on official Proxmark3 Master?
|
## Why didn't you base it on official Proxmark3 Master?
|
||||||
|
|
||||||
|
@ -132,14 +160,9 @@ The separation from official Proxmark3 repo gives us a lot of freedom to create
|
||||||
|
|
||||||
## Proxmark3 GUI
|
## Proxmark3 GUI
|
||||||
|
|
||||||
The official PM3-GUI from Gaucho will not work.
|
The official PM3-GUI from Gaucho will not work. Not to mention is quite old and not maintained any longer.
|
||||||
The new [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) will work more or less. Change is needed in order to show helptext when client isn't connected to a device. We don't know how active the maintainers.
|
|
||||||
|
|
||||||
## The end
|
The new [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) will work more or less. Change is needed in order to show helptext when client isn't connected to a device. We don't know how active the maintainers are. There has been brought to our attention that there is quite a few Chinese Windows GUI available. Usually you find them on alibaba / taobao ads but we have no idea which fw/client they are compatible with. Proceed with caution if you decide to go down that road.
|
||||||
|
|
||||||
- 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
|
# Donations
|
||||||
|
|
||||||
|
|
|
@ -64,8 +64,12 @@ clone_script:
|
||||||
WSLExec "WSL update..." "sudo apt-get update 1>/dev/null"
|
WSLExec "WSL update..." "sudo apt-get update 1>/dev/null"
|
||||||
WSLExec "WSL upgrade..." "sudo apt-get upgrade -y 1>/dev/null"
|
WSLExec "WSL upgrade..." "sudo apt-get upgrade -y 1>/dev/null"
|
||||||
WSLExec "WSL cleanup..." "sudo apt-get auto-remove -y 1>/dev/null"
|
WSLExec "WSL cleanup..." "sudo apt-get auto-remove -y 1>/dev/null"
|
||||||
WSLExec "WSL install..." "sudo apt-get -y install --reinstall --no-install-recommends git ca-certificates build-essential pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev qtbase5-dev cmake 1>/dev/null"
|
WSLExec "WSL install..." "sudo apt-get -y install --reinstall --no-install-recommends git ca-certificates build-essential pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev qtbase5-dev cmake libpython3-dev python3 python3-pip python3-dev libpython3-all-dev 1>/dev/null"
|
||||||
WSLExec "WSL QT fix..." "sudo strip --remove-section=.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.so.5"
|
WSLExec "WSL QT fix..." "sudo strip --remove-section=.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.so.5"
|
||||||
|
WSLExec "WSL install python dependencies..." "sudo python3 -m pip install --upgrade pip 1>/dev/null"
|
||||||
|
WSLExec "WSL install pip..." "sudo python3 -m pip install setuptools 1>/dev/null"
|
||||||
|
WSLExec "WSL install pip continue..." "sudo python3 -m pip install ansicolors sslcrypto 1>/dev/null"
|
||||||
|
|
||||||
Add-AppveyorMessage -Message "WSL setup took $(([System.Environment]::TickCount-$WSLInstallTime) / 1000) sec" -Category Information
|
Add-AppveyorMessage -Message "WSL setup took $(([System.Environment]::TickCount-$WSLInstallTime) / 1000) sec" -Category Information
|
||||||
New-Item -ItemType "file" -Path "C:\WSL-Finished.txt" -Force | Out-Null
|
New-Item -ItemType "file" -Path "C:\WSL-Finished.txt" -Force | Out-Null
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,8 +217,12 @@ $(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z
|
||||||
$(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@
|
$(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@
|
||||||
|
|
||||||
$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o
|
$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o
|
||||||
|
ifeq (,$(findstring WITH_NO_COMPRESSION,$(APP_CFLAGS)))
|
||||||
$(info [=] LD $@)
|
$(info [=] LD $@)
|
||||||
$(Q)$(CC) $(CROSS_LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^
|
$(Q)$(CC) $(CROSS_LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^
|
||||||
|
else
|
||||||
|
$(Q)$(CP) $(OBJDIR)/fullimage.stage1.elf $@
|
||||||
|
endif
|
||||||
|
|
||||||
tarbin: $(OBJS)
|
tarbin: $(OBJS)
|
||||||
$(info TAR $@)
|
$(info TAR $@)
|
||||||
|
|
|
@ -35,6 +35,9 @@ define KNOWN_STANDALONE_DEFINITIONS
|
||||||
| LF_SAMYRUN | HID26 read/clone/sim |
|
| LF_SAMYRUN | HID26 read/clone/sim |
|
||||||
| | - Samy Kamkar |
|
| | - Samy Kamkar |
|
||||||
+----------------------------------------------------------+
|
+----------------------------------------------------------+
|
||||||
|
| LF_THAREXDE | Simulate/read EM4x50 tags |
|
||||||
|
| (RDV4 only) | storing in flashmem |
|
||||||
|
+----------------------------------------------------------+
|
||||||
| HF_14ASNIFF | 14a sniff to flashmem |
|
| HF_14ASNIFF | 14a sniff to flashmem |
|
||||||
| (RDV4 only) | |
|
| (RDV4 only) | |
|
||||||
+----------------------------------------------------------+
|
+----------------------------------------------------------+
|
||||||
|
@ -67,10 +70,10 @@ define KNOWN_STANDALONE_DEFINITIONS
|
||||||
+----------------------------------------------------------+
|
+----------------------------------------------------------+
|
||||||
endef
|
endef
|
||||||
|
|
||||||
STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN
|
STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE
|
||||||
STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_YOUNG
|
STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_YOUNG
|
||||||
STANDALONE_MODES_REQ_SMARTCARD :=
|
STANDALONE_MODES_REQ_SMARTCARD :=
|
||||||
STANDALONE_MODES_REQ_FLASH := LF_ICEHID HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS
|
STANDALONE_MODES_REQ_FLASH := LF_ICEHID LF_THAREXDE HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS
|
||||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
|
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
|
||||||
STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE)
|
STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE)
|
||||||
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),)
|
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),)
|
||||||
|
|
|
@ -73,3 +73,7 @@ endif
|
||||||
ifneq (,$(findstring WITH_STANDALONE_HF_ICECLASS,$(APP_CFLAGS)))
|
ifneq (,$(findstring WITH_STANDALONE_HF_ICECLASS,$(APP_CFLAGS)))
|
||||||
SRC_STANDALONE = hf_iceclass.c
|
SRC_STANDALONE = hf_iceclass.c
|
||||||
endif
|
endif
|
||||||
|
# WITH_STANDALONE_LF_THAREXDE
|
||||||
|
ifneq (,$(findstring WITH_STANDALONE_LF_THAREXDE,$(APP_CFLAGS)))
|
||||||
|
SRC_STANDALONE = lf_tharexde.c
|
||||||
|
endif
|
||||||
|
|
|
@ -68,11 +68,11 @@ uint16_t get_ev1_version(iso14a_card_select_t card, uint8_t *version) {
|
||||||
return mifare_sendcmd(MIFARE_ULEV1_VERSION, NULL, 0, version, NULL, NULL);
|
return mifare_sendcmd(MIFARE_ULEV1_VERSION, NULL, 0, version, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t get_ev1_signature(iso14a_card_select_t card, uint8_t *response) {
|
uint16_t get_ev1_signature(iso14a_card_select_t card, uint8_t *signature) {
|
||||||
uint8_t cmd[4] = {MIFARE_ULEV1_READSIG, 0x00, 0x00, 0x00};
|
uint8_t cmd[4] = {MIFARE_ULEV1_READSIG, 0x00, 0x00, 0x00};
|
||||||
AddCrc14A(cmd, 2);
|
AddCrc14A(cmd, 2);
|
||||||
ReaderTransmit(cmd, sizeof(cmd), NULL);
|
ReaderTransmit(cmd, sizeof(cmd), NULL);
|
||||||
return ReaderReceive(response, NULL);
|
return ReaderReceive(signature, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t get_ev1_counter(iso14a_card_select_t card, uint8_t counter, uint8_t *response) {
|
uint16_t get_ev1_counter(iso14a_card_select_t card, uint8_t counter, uint8_t *response) {
|
||||||
|
@ -114,7 +114,6 @@ int get_block_count(iso14a_card_select_t card, uint8_t version[], uint16_t versi
|
||||||
else if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0E", 7) == 0) { block_count = MAX_ULEV1b_BLOCKS; }
|
else if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0E", 7) == 0) { block_count = MAX_ULEV1b_BLOCKS; }
|
||||||
else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0E", 7) == 0) { block_count = MAX_ULEV1b_BLOCKS; }
|
else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0E", 7) == 0) { block_count = MAX_ULEV1b_BLOCKS; }
|
||||||
else if (memcmp(version, "\x00\x34\x21\x01\x01\x00\x0E", 7) == 0) { block_count = MAX_ULEV1b_BLOCKS; } // Mikron JSC Russia EV1 41 pages tag
|
else if (memcmp(version, "\x00\x34\x21\x01\x01\x00\x0E", 7) == 0) { block_count = MAX_ULEV1b_BLOCKS; } // Mikron JSC Russia EV1 41 pages tag
|
||||||
else if (memcmp(version, "\x00\x34\x21\x01\x01\x00\x0E", 7) == 0) { block_count = MAX_UL_BLOCKS; }
|
|
||||||
else if (version[2] == 0x03) { block_count = MAX_ULEV1a_BLOCKS; }
|
else if (version[2] == 0x03) { block_count = MAX_ULEV1a_BLOCKS; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +190,7 @@ void RunMod(void) {
|
||||||
read_successful = false;
|
read_successful = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// We're skipping 14 blocks (56 bytes) here, as that "[...] has version/signature/counter data here" according to comments on hf_mfu_dumptoemulator
|
// We're skipping 14 blocks (56 bytes) here, as that "[...] has version/signature/counter data here" according to comments on data_mfu_bin2eml
|
||||||
// When converting a bin, it's almost all 0 other than one 0x0F byte, and functionality seems to be unaffected if that byte is set to 0x00.
|
// When converting a bin, it's almost all 0 other than one 0x0F byte, and functionality seems to be unaffected if that byte is set to 0x00.
|
||||||
emlSetMem_xt(dataout, 14 + i, 1, 4);
|
emlSetMem_xt(dataout, 14 + i, 1, 4);
|
||||||
Dbhexdump(4, dataout, 0);
|
Dbhexdump(4, dataout, 0);
|
||||||
|
|
|
@ -37,15 +37,19 @@
|
||||||
#define ICE_STATE_ATTACK 2
|
#define ICE_STATE_ATTACK 2
|
||||||
#define ICE_STATE_READER 3
|
#define ICE_STATE_READER 3
|
||||||
#define ICE_STATE_CONFIGCARD 4
|
#define ICE_STATE_CONFIGCARD 4
|
||||||
|
#define ICE_STATE_DUMP_SIM 5
|
||||||
|
|
||||||
|
#define HF_ICLASS_NUM_MODES 6
|
||||||
|
|
||||||
// ====================================================
|
// ====================================================
|
||||||
// Select which standalone function to be active.
|
// Select which standalone function to be active.
|
||||||
// 4 possiblities. Uncomment the one you wanna use.
|
// 5 possiblities. Uncomment the one you wanna use.
|
||||||
|
|
||||||
#define ICE_USE ICE_STATE_FULLSIM
|
#define ICE_USE ICE_STATE_FULLSIM
|
||||||
//#define ICE_USE ICE_STATE_ATTACK
|
//#define ICE_USE ICE_STATE_ATTACK
|
||||||
//#define ICE_USE ICE_STATE_READER
|
//#define ICE_USE ICE_STATE_READER
|
||||||
//#define ICE_USE ICE_STATE_CONFIGCARD
|
//#define ICE_USE ICE_STATE_CONFIGCARD
|
||||||
|
//#define ICE_USE ICE_STATE_DUMP_SIM
|
||||||
|
|
||||||
// ====================================================
|
// ====================================================
|
||||||
|
|
||||||
|
@ -53,6 +57,8 @@
|
||||||
#define NUM_CSNS 9
|
#define NUM_CSNS 9
|
||||||
#define MAC_RESPONSES_SIZE (16 * NUM_CSNS)
|
#define MAC_RESPONSES_SIZE (16 * NUM_CSNS)
|
||||||
#define HF_ICLASS_FULLSIM_ORIG_BIN "iceclass-orig.bin"
|
#define HF_ICLASS_FULLSIM_ORIG_BIN "iceclass-orig.bin"
|
||||||
|
#define HF_ICALSSS_READSIM_TEMP_BIN "iceclass-temp.bin"
|
||||||
|
#define HF_ICALSSS_READSIM_TEMP_MOD_BIN "iceclass-temp-mod.bin"
|
||||||
#define HF_ICLASS_FULLSIM_MOD "iceclass-modified"
|
#define HF_ICLASS_FULLSIM_MOD "iceclass-modified"
|
||||||
#define HF_ICLASS_FULLSIM_MOD_BIN HF_ICLASS_FULLSIM_MOD".bin"
|
#define HF_ICLASS_FULLSIM_MOD_BIN HF_ICLASS_FULLSIM_MOD".bin"
|
||||||
#define HF_ICLASS_FULLSIM_MOD_EML HF_ICLASS_FULLSIM_MOD".eml"
|
#define HF_ICLASS_FULLSIM_MOD_EML HF_ICLASS_FULLSIM_MOD".eml"
|
||||||
|
@ -141,20 +147,33 @@ static void download_instructions(uint8_t t) {
|
||||||
DbpString("2. " _YELLOW_("mem spiffs dump h"));
|
DbpString("2. " _YELLOW_("mem spiffs dump h"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ICE_STATE_DUMP_SIM: {
|
||||||
|
DbpString("The found tag will be dumped to " HF_ICALSSS_READSIM_TEMP_BIN);
|
||||||
|
DbpString("1. " _YELLOW_("mem spiffs tree"));
|
||||||
|
DbpString("2. " _YELLOW_("mem spiffs dump h"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save to flash if file doesn't exist.
|
// Save to flash if file doesn't exist.
|
||||||
// Write over file if size of flash file is less than new datalen
|
// Write over file if size of flash file is less than new datalen
|
||||||
static void save_to_flash(uint8_t *data, uint16_t datalen) {
|
static void save_to_flash(uint8_t *data, uint16_t datalen, char *filename) {
|
||||||
|
|
||||||
rdv40_spiffs_lazy_mount();
|
rdv40_spiffs_lazy_mount();
|
||||||
|
|
||||||
char fn[SPIFFS_OBJ_NAME_LEN];
|
char fn[SPIFFS_OBJ_NAME_LEN];
|
||||||
|
|
||||||
|
if (filename == NULL) {
|
||||||
sprintf(fn, "iclass-%02X%02X%02X%02X%02X%02X%02X%02X.bin",
|
sprintf(fn, "iclass-%02X%02X%02X%02X%02X%02X%02X%02X.bin",
|
||||||
data[0], data[1], data[2], data[3],
|
data[0], data[1], data[2], data[3],
|
||||||
data[4], data[5], data[6], data[7]
|
data[4], data[5], data[6], data[7]
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
int fnlen = MIN(strlen(filename), SPIFFS_OBJ_NAME_LEN);
|
||||||
|
// if the given name len longer than buffer allows, cut it down to size
|
||||||
|
memcpy(fn, filename, fnlen);
|
||||||
|
}
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
if (exists_in_spiffs(fn) == false) {
|
if (exists_in_spiffs(fn) == false) {
|
||||||
|
@ -400,13 +419,180 @@ static int reader_dump_mode(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch_off();
|
switch_off();
|
||||||
save_to_flash(card_data, (start_block + dumped) * 8);
|
save_to_flash(card_data, (start_block + dumped) * 8, NULL);
|
||||||
Dbprintf("%u bytes saved", (start_block + dumped) * 8);
|
Dbprintf("%u bytes saved", (start_block + dumped) * 8);
|
||||||
}
|
}
|
||||||
DbpString("-=[ exiting " _CYAN_("`read & dump`") " mode ]=-");
|
DbpString("-=[ exiting " _CYAN_("`read & dump`") " mode ]=-");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dump_sim_mode(void) {
|
||||||
|
|
||||||
|
DbpString("this mode has no tracelog");
|
||||||
|
if (have_aa2())
|
||||||
|
DbpString("dumping of " _YELLOW_("AA2 enabled"));
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
BigBuf_free();
|
||||||
|
|
||||||
|
uint8_t *card_data = BigBuf_malloc(ICLASS_16KS_SIZE);
|
||||||
|
memset(card_data, 0xFF, ICLASS_16KS_SIZE);
|
||||||
|
|
||||||
|
if (BUTTON_PRESS()) {
|
||||||
|
DbpString("button pressed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup authenticate AA1
|
||||||
|
iclass_auth_req_t auth = {
|
||||||
|
.use_raw = false,
|
||||||
|
.use_elite = false,
|
||||||
|
.use_credit_key = false,
|
||||||
|
.do_auth = true,
|
||||||
|
.send_reply = false,
|
||||||
|
};
|
||||||
|
memcpy(auth.key, legacy_aa1_key, sizeof(auth.key));
|
||||||
|
|
||||||
|
Iso15693InitReader();
|
||||||
|
set_tracing(false);
|
||||||
|
|
||||||
|
|
||||||
|
picopass_hdr *hdr = (picopass_hdr *)card_data;
|
||||||
|
|
||||||
|
// select tag.
|
||||||
|
uint32_t eof_time = 0;
|
||||||
|
bool res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time);
|
||||||
|
if (res == false) {
|
||||||
|
switch_off();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanity check of CSN.
|
||||||
|
if (hdr->csn[7] != 0xE0 && hdr->csn[6] != 0x12) {
|
||||||
|
switch_off();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||||
|
|
||||||
|
// get 3 config bits
|
||||||
|
uint8_t type = (hdr->conf.chip_config & 0x10) >> 2;
|
||||||
|
type |= (hdr->conf.mem_config & 0x80) >> 6;
|
||||||
|
type |= (hdr->conf.mem_config & 0x20) >> 5;
|
||||||
|
|
||||||
|
Dbprintf(_GREEN_("%s") ", dumping...", card_types[type]);
|
||||||
|
|
||||||
|
uint8_t pagemap = get_pagemap(hdr);
|
||||||
|
uint8_t app1_limit, app2_limit, start_block;
|
||||||
|
|
||||||
|
// tags configured for NON SECURE PAGE, acts different
|
||||||
|
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||||
|
app1_limit = card_app2_limit[type];
|
||||||
|
app2_limit = 0;
|
||||||
|
start_block = 3;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
app1_limit = hdr->conf.app_limit;
|
||||||
|
app2_limit = card_app2_limit[type];
|
||||||
|
start_block = 5;
|
||||||
|
|
||||||
|
res = authenticate_iclass_tag(&auth, hdr, &start_time, &eof_time, NULL);
|
||||||
|
if (res == false) {
|
||||||
|
switch_off();
|
||||||
|
Dbprintf(_RED_("failed AA1 auth") ", skipping ");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t dumped = 0;
|
||||||
|
|
||||||
|
// main read loop
|
||||||
|
for (uint16_t i = start_block; i <= app1_limit; i++) {
|
||||||
|
if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time)) {
|
||||||
|
dumped++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pagemap != PICOPASS_NON_SECURE_PAGEMODE && have_aa2()) {
|
||||||
|
|
||||||
|
// authenticate AA2
|
||||||
|
auth.use_raw = false;
|
||||||
|
auth.use_credit_key = true;
|
||||||
|
memcpy(auth.key, aa2_key, sizeof(auth.key));
|
||||||
|
|
||||||
|
res = select_iclass_tag(hdr, auth.use_credit_key, &eof_time);
|
||||||
|
if (res) {
|
||||||
|
|
||||||
|
// sanity check of CSN.
|
||||||
|
if (hdr->csn[7] != 0xE0 && hdr->csn[6] != 0x12) {
|
||||||
|
switch_off();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = authenticate_iclass_tag(&auth, hdr, &start_time, &eof_time, NULL);
|
||||||
|
if (res) {
|
||||||
|
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||||
|
|
||||||
|
for (uint16_t i = app1_limit + 1; i <= app2_limit; i++) {
|
||||||
|
if (iclass_read_block(i, card_data + (8 * i), &start_time, &eof_time)) {
|
||||||
|
dumped++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DbpString(_RED_("failed AA2 auth"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DbpString(_RED_("failed selecting AA2"));
|
||||||
|
|
||||||
|
// sanity check of CSN.
|
||||||
|
if (hdr->csn[7] != 0xE0 && hdr->csn[6] != 0x12) {
|
||||||
|
switch_off();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch_off();
|
||||||
|
char *temp_file = HF_ICALSSS_READSIM_TEMP_BIN;
|
||||||
|
save_to_flash(card_data, (start_block + dumped) * 8, temp_file);
|
||||||
|
Dbprintf("%u bytes saved", (start_block + dumped) * 8);
|
||||||
|
|
||||||
|
if (((start_block + dumped) * 8) > 0) {
|
||||||
|
break; //switch to sim mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rdv40_spiffs_lazy_mount();
|
||||||
|
|
||||||
|
SpinOff(0);
|
||||||
|
uint8_t *emul = BigBuf_get_EM_addr();
|
||||||
|
uint32_t fsize = size_in_spiffs(HF_ICALSSS_READSIM_TEMP_BIN);
|
||||||
|
int res = rdv40_spiffs_read_as_filetype(HF_ICALSSS_READSIM_TEMP_BIN, emul, fsize, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
|
rdv40_spiffs_lazy_unmount();
|
||||||
|
if (res == SPIFFS_OK) {
|
||||||
|
Dbprintf("loaded " _GREEN_(HF_ICALSSS_READSIM_TEMP_BIN) " (%u bytes)", fsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dbprintf("simming " _GREEN_(HF_ICALSSS_READSIM_TEMP_BIN));
|
||||||
|
iclass_simulate(ICLASS_SIM_MODE_FULL, 0, false, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
LED_B_ON();
|
||||||
|
rdv40_spiffs_lazy_mount();
|
||||||
|
res = rdv40_spiffs_write(HF_ICALSSS_READSIM_TEMP_BIN, emul, fsize, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
|
rdv40_spiffs_lazy_unmount();
|
||||||
|
LED_B_OFF();
|
||||||
|
if (res == SPIFFS_OK) {
|
||||||
|
Dbprintf("wrote emulator memory to " _GREEN_(HF_ICALSSS_READSIM_TEMP_MOD_BIN));
|
||||||
|
} else {
|
||||||
|
Dbprintf(_RED_("error") " writing "HF_ICALSSS_READSIM_TEMP_MOD_BIN" to flash ( %d )", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
DbpString("-=[ exiting " _CYAN_("`dump & sim`") " mode ]=-");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int config_sim_mode(void) {
|
static int config_sim_mode(void) {
|
||||||
|
|
||||||
uint8_t *emul = BigBuf_get_EM_addr();
|
uint8_t *emul = BigBuf_get_EM_addr();
|
||||||
|
@ -436,7 +622,7 @@ void RunMod(void) {
|
||||||
|
|
||||||
uint8_t mode = ICE_USE;
|
uint8_t mode = ICE_USE;
|
||||||
uint8_t *bb = BigBuf_get_EM_addr();
|
uint8_t *bb = BigBuf_get_EM_addr();
|
||||||
if (bb[0] > 0 && bb[0] < 5) {
|
if (bb[0] > 0 && bb[0] < HF_ICLASS_NUM_MODES) {
|
||||||
mode = bb[0];
|
mode = bb[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,6 +698,16 @@ void RunMod(void) {
|
||||||
if (mode == ICE_STATE_CONFIGCARD)
|
if (mode == ICE_STATE_CONFIGCARD)
|
||||||
config_sim_mode();
|
config_sim_mode();
|
||||||
|
|
||||||
|
mode = ICE_STATE_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ICE_STATE_DUMP_SIM: {
|
||||||
|
DbpString("-=[ enter " _CYAN_("`dump & sim`") " mode, read 1 card and sim it ]=-");
|
||||||
|
res = dump_sim_mode();
|
||||||
|
if (res == PM3_SUCCESS) {
|
||||||
|
download_instructions(mode);
|
||||||
|
}
|
||||||
|
|
||||||
mode = ICE_STATE_NONE;
|
mode = ICE_STATE_NONE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,11 +248,9 @@ void RunMod(void) {
|
||||||
dynamic_response_info.response[0] = receivedCmd[0];
|
dynamic_response_info.response[0] = receivedCmd[0];
|
||||||
|
|
||||||
if (memcmp("\x02\xa2\xb0\x00\x00\x1d\x51\x69", receivedCmd, 8) == 0) {
|
if (memcmp("\x02\xa2\xb0\x00\x00\x1d\x51\x69", receivedCmd, 8) == 0) {
|
||||||
dynamic_response_info.response[0] = receivedCmd[0];
|
|
||||||
memcpy(dynamic_response_info.response + 1, ndef, 31);
|
memcpy(dynamic_response_info.response + 1, ndef, 31);
|
||||||
dynamic_response_info.response_n = 32;
|
dynamic_response_info.response_n = 32;
|
||||||
} else if (memcmp("\x02\x00\x20\x00\x01\x00\x6e\xa9", receivedCmd, 8) == 0) {
|
} else if (memcmp("\x02\x00\x20\x00\x01\x00\x6e\xa9", receivedCmd, 8) == 0) {
|
||||||
dynamic_response_info.response[0] = receivedCmd[0];
|
|
||||||
dynamic_response_info.response[1] = 0x63;
|
dynamic_response_info.response[1] = 0x63;
|
||||||
dynamic_response_info.response[2] = 0x00;
|
dynamic_response_info.response[2] = 0x00;
|
||||||
dynamic_response_info.response_n = 3;
|
dynamic_response_info.response_n = 3;
|
||||||
|
@ -260,14 +258,12 @@ void RunMod(void) {
|
||||||
memcpy(verify_pwd + 5, receivedCmd + 6, 16);
|
memcpy(verify_pwd + 5, receivedCmd + 6, 16);
|
||||||
DbpString("Reader sent password: ");
|
DbpString("Reader sent password: ");
|
||||||
Dbhexdump(16, verify_pwd + 5, 0);
|
Dbhexdump(16, verify_pwd + 5, 0);
|
||||||
dynamic_response_info.response[0] = receivedCmd[0];
|
|
||||||
dynamic_response_info.response[1] = 0x90;
|
dynamic_response_info.response[1] = 0x90;
|
||||||
dynamic_response_info.response[2] = 0x00;
|
dynamic_response_info.response[2] = 0x00;
|
||||||
dynamic_response_info.response_n = 3;
|
dynamic_response_info.response_n = 3;
|
||||||
gotkey = true;
|
gotkey = true;
|
||||||
state = STATE_DUMP;
|
state = STATE_DUMP;
|
||||||
} else {
|
} else {
|
||||||
dynamic_response_info.response[0] = receivedCmd[0];
|
|
||||||
dynamic_response_info.response[1] = 0x90;
|
dynamic_response_info.response[1] = 0x90;
|
||||||
dynamic_response_info.response[2] = 0x00;
|
dynamic_response_info.response[2] = 0x00;
|
||||||
dynamic_response_info.response_n = 3;
|
dynamic_response_info.response_n = 3;
|
||||||
|
@ -321,7 +317,7 @@ void RunMod(void) {
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apdusLen[i], false, apdubuffer, NULL);
|
uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apdusLen[i], false, apdubuffer, NULL);
|
||||||
|
|
||||||
if (apdulen > 0) {
|
if (apdulen > 2) {
|
||||||
DbpString(_YELLOW_("[ ") "Proxmark command" _YELLOW_(" ]"));
|
DbpString(_YELLOW_("[ ") "Proxmark command" _YELLOW_(" ]"));
|
||||||
Dbhexdump(apdusLen[i], apdus[i], false);
|
Dbhexdump(apdusLen[i], apdus[i], false);
|
||||||
DbpString(_GREEN_("[ ") "Card answer" _GREEN_(" ]"));
|
DbpString(_GREEN_("[ ") "Card answer" _GREEN_(" ]"));
|
||||||
|
@ -429,11 +425,9 @@ void RunMod(void) {
|
||||||
dynamic_response_info.response[0] = receivedCmd[0];
|
dynamic_response_info.response[0] = receivedCmd[0];
|
||||||
|
|
||||||
if (memcmp("\x02\xa2\xb0\x00\x00\x1d\x51\x69", receivedCmd, 8) == 0) {
|
if (memcmp("\x02\xa2\xb0\x00\x00\x1d\x51\x69", receivedCmd, 8) == 0) {
|
||||||
dynamic_response_info.response[0] = receivedCmd[0];
|
|
||||||
memcpy(dynamic_response_info.response + 1, ndef, 31);
|
memcpy(dynamic_response_info.response + 1, ndef, 31);
|
||||||
dynamic_response_info.response_n = 32;
|
dynamic_response_info.response_n = 32;
|
||||||
} else if (memcmp("\x02\x00\x20\x00\x01\x00\x6e\xa9", receivedCmd, 8) == 0) {
|
} else if (memcmp("\x02\x00\x20\x00\x01\x00\x6e\xa9", receivedCmd, 8) == 0) {
|
||||||
dynamic_response_info.response[0] = receivedCmd[0];
|
|
||||||
dynamic_response_info.response[1] = 0x63;
|
dynamic_response_info.response[1] = 0x63;
|
||||||
dynamic_response_info.response[2] = 0x00;
|
dynamic_response_info.response[2] = 0x00;
|
||||||
dynamic_response_info.response_n = 3;
|
dynamic_response_info.response_n = 3;
|
||||||
|
@ -441,12 +435,10 @@ void RunMod(void) {
|
||||||
memcpy(verify_pwd + 5, receivedCmd + 6, 16);
|
memcpy(verify_pwd + 5, receivedCmd + 6, 16);
|
||||||
DbpString("Reader sent password: ");
|
DbpString("Reader sent password: ");
|
||||||
Dbhexdump(16, verify_pwd + 5, 0);
|
Dbhexdump(16, verify_pwd + 5, 0);
|
||||||
dynamic_response_info.response[0] = receivedCmd[0];
|
|
||||||
dynamic_response_info.response[1] = 0x90;
|
dynamic_response_info.response[1] = 0x90;
|
||||||
dynamic_response_info.response[2] = 0x00;
|
dynamic_response_info.response[2] = 0x00;
|
||||||
dynamic_response_info.response_n = 3;
|
dynamic_response_info.response_n = 3;
|
||||||
} else {
|
} else {
|
||||||
dynamic_response_info.response[0] = receivedCmd[0];
|
|
||||||
dynamic_response_info.response[1] = 0x90;
|
dynamic_response_info.response[1] = 0x90;
|
||||||
dynamic_response_info.response[2] = 0x00;
|
dynamic_response_info.response[2] = 0x00;
|
||||||
dynamic_response_info.response_n = 3;
|
dynamic_response_info.response_n = 3;
|
||||||
|
|
|
@ -21,19 +21,19 @@
|
||||||
#include "commonutil.h"
|
#include "commonutil.h"
|
||||||
|
|
||||||
#define MAX_IND 16 // 4 LEDs - 2^4 combinations
|
#define MAX_IND 16 // 4 LEDs - 2^4 combinations
|
||||||
#define CLOCK 64 //for 125kHz
|
#define LF_CLOCK 64 // for 125kHz
|
||||||
|
|
||||||
// low & high - array for storage IDs. Its length must be equal.
|
// low & high - array for storage IDs. Its length must be equal.
|
||||||
// Predefined IDs must be stored in low[].
|
// Predefined IDs must be stored in low[].
|
||||||
static uint64_t low[] = {0x565A1140BE, 0x365A398149, 0x5555555555, 0xFFFFFFFFFF};
|
static uint64_t low[] = {0x565A1140BE, 0x365A398149, 0x5555555555, 0xFFFFFFFFFF};
|
||||||
static uint8_t *bba, slots_count;
|
static uint8_t slots_count;
|
||||||
static int buflen;
|
static int buflen;
|
||||||
|
|
||||||
void ModInfo(void) {
|
void ModInfo(void) {
|
||||||
DbpString(" LF EM4100 simulator standalone mode");
|
DbpString(" LF EM4100 simulator standalone mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t ReversQuads(uint64_t bits) {
|
static uint64_t rev_quads(uint64_t bits) {
|
||||||
uint64_t result = 0;
|
uint64_t result = 0;
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i);
|
result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i);
|
||||||
|
@ -41,32 +41,40 @@ static uint64_t ReversQuads(uint64_t bits) {
|
||||||
return result >> 24;
|
return result >> 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FillBuff(uint8_t bit) {
|
static void fill_buff(uint8_t bit) {
|
||||||
memset(bba + buflen, bit, CLOCK / 2);
|
uint8_t *bba = BigBuf_get_addr();
|
||||||
buflen += (CLOCK / 2);
|
memset(bba + buflen, bit, LF_CLOCK / 2);
|
||||||
memset(bba + buflen, bit ^ 1, CLOCK / 2);
|
buflen += (LF_CLOCK / 2);
|
||||||
buflen += (CLOCK / 2);
|
memset(bba + buflen, bit ^ 1, LF_CLOCK / 2);
|
||||||
|
buflen += (LF_CLOCK / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ConstructEM410xEmulBuf(uint64_t id) {
|
static void construct_EM410x_emul(uint64_t id) {
|
||||||
|
|
||||||
int i, j, binary[4], parity[4];
|
int i, j;
|
||||||
|
int binary[4] = {0, 0, 0, 0};
|
||||||
|
int parity[4] = {0, 0, 0, 0};
|
||||||
buflen = 0;
|
buflen = 0;
|
||||||
|
|
||||||
for (i = 0; i < 9; i++)
|
for (i = 0; i < 9; i++)
|
||||||
FillBuff(1);
|
fill_buff(1);
|
||||||
parity[0] = parity[1] = parity[2] = parity[3] = 0;
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
for (j = 3; j >= 0; j--, id /= 2)
|
for (j = 3; j >= 0; j--, id /= 2)
|
||||||
binary[j] = id % 2;
|
binary[j] = id % 2;
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
FillBuff(binary[j]);
|
fill_buff(binary[j]);
|
||||||
FillBuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
|
||||||
|
fill_buff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
parity[j] ^= binary[j];
|
parity[j] ^= binary[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
FillBuff(parity[j]);
|
fill_buff(parity[j]);
|
||||||
FillBuff(0);
|
|
||||||
|
fill_buff(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LED_Slot(int i) {
|
static void LED_Slot(int i) {
|
||||||
|
@ -85,14 +93,14 @@ void RunMod(void) {
|
||||||
|
|
||||||
int selected = 0; //selected slot after start
|
int selected = 0; //selected slot after start
|
||||||
slots_count = ARRAYLEN(low);
|
slots_count = ARRAYLEN(low);
|
||||||
bba = BigBuf_get_addr();
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (data_available()) break;
|
if (data_available()) break;
|
||||||
|
|
||||||
SpinDelay(100);
|
SpinDelay(100);
|
||||||
SpinUp(100);
|
SpinUp(100);
|
||||||
LED_Slot(selected);
|
LED_Slot(selected);
|
||||||
ConstructEM410xEmulBuf(ReversQuads(low[selected]));
|
construct_EM410x_emul(rev_quads(low[selected]));
|
||||||
SimulateTagLowFrequency(buflen, 0, true);
|
SimulateTagLowFrequency(buflen, 0, true);
|
||||||
selected = (selected + 1) % slots_count;
|
selected = (selected + 1) % slots_count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,8 +53,8 @@
|
||||||
#include "flashmem.h"
|
#include "flashmem.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LF_CLOCK 64 //for 125kHz
|
#define LF_CLOCK 64 // for 125kHz
|
||||||
#define LF_RWSB_T55XX_TYPE 1 //Tag type: 0 - T5555, 1-T55x7
|
#define LF_RWSB_T55XX_TYPE 1 // Tag type: 0 - T5555, 1-T55x7
|
||||||
|
|
||||||
#define LF_RWSB_UNKNOWN_RESULT 0
|
#define LF_RWSB_UNKNOWN_RESULT 0
|
||||||
#define LF_RWSB_BRUTE_STOPED 1
|
#define LF_RWSB_BRUTE_STOPED 1
|
||||||
|
@ -76,14 +76,13 @@ static int bruteforceSpeed[] = {10, 12, 14, 16};
|
||||||
// In high[] must be nulls
|
// In high[] must be nulls
|
||||||
static uint64_t low[] = {0, 0, 0, 0};
|
static uint64_t low[] = {0, 0, 0, 0};
|
||||||
static uint32_t high[] = {0, 0, 0, 0};
|
static uint32_t high[] = {0, 0, 0, 0};
|
||||||
static uint8_t *bba;
|
|
||||||
static int buflen;
|
static int buflen;
|
||||||
|
|
||||||
void ModInfo(void) {
|
void ModInfo(void) {
|
||||||
DbpString(" LF EM4100 read/sim/write/brute mode");
|
DbpString(" LF EM4100 read/sim/write/brute mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t ReversQuads(uint64_t bits) {
|
static uint64_t rev_quads(uint64_t bits) {
|
||||||
uint64_t result = 0;
|
uint64_t result = 0;
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i);
|
result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i);
|
||||||
|
@ -91,33 +90,39 @@ static uint64_t ReversQuads(uint64_t bits) {
|
||||||
return result >> 24;
|
return result >> 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FillBuff(uint8_t bit) {
|
static void fill_buff(uint8_t bit) {
|
||||||
|
uint8_t *bba = BigBuf_get_addr();
|
||||||
memset(bba + buflen, bit, LF_CLOCK / 2);
|
memset(bba + buflen, bit, LF_CLOCK / 2);
|
||||||
buflen += (LF_CLOCK / 2);
|
buflen += (LF_CLOCK / 2);
|
||||||
memset(bba + buflen, bit ^ 1, LF_CLOCK / 2);
|
memset(bba + buflen, bit ^ 1, LF_CLOCK / 2);
|
||||||
buflen += (LF_CLOCK / 2);
|
buflen += (LF_CLOCK / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ConstructEM410xEmulBuf(uint64_t id) {
|
static void construct_EM410x_emul(uint64_t id) {
|
||||||
bba = BigBuf_get_addr();
|
int i, j;
|
||||||
|
int binary[4] = {0, 0, 0, 0};
|
||||||
int i, j, binary[4], parity[4];
|
int parity[4] = {0, 0, 0, 0};
|
||||||
buflen = 0;
|
buflen = 0;
|
||||||
|
|
||||||
for (i = 0; i < 9; i++)
|
for (i = 0; i < 9; i++)
|
||||||
FillBuff(1);
|
fill_buff(1);
|
||||||
parity[0] = parity[1] = parity[2] = parity[3] = 0;
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
for (j = 3; j >= 0; j--, id /= 2)
|
for (j = 3; j >= 0; j--, id /= 2)
|
||||||
binary[j] = id % 2;
|
binary[j] = id % 2;
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
FillBuff(binary[j]);
|
fill_buff(binary[j]);
|
||||||
FillBuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
|
||||||
|
fill_buff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
parity[j] ^= binary[j];
|
parity[j] ^= binary[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
FillBuff(parity[j]);
|
fill_buff(parity[j]);
|
||||||
FillBuff(0);
|
|
||||||
|
fill_buff(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LED_Update(int mode, int slot) {
|
static void LED_Update(int mode, int slot) {
|
||||||
|
@ -188,8 +193,8 @@ static uint64_t PackEmID(uint64_t original, int newCardNum) {
|
||||||
buf &= ~(1 << i);
|
buf &= ~(1 << i);
|
||||||
}
|
}
|
||||||
buf |= (newCardNum & 0xFFFF) << 1;
|
buf |= (newCardNum & 0xFFFF) << 1;
|
||||||
buf |= oddparity32((buf >> 1) & 0xFFF) & 1;
|
buf |= oddparity32((buf >> 1) & 0xFFF);
|
||||||
buf |= (evenparity32((buf >> 13) & 0xFFF) & 1) << 25;
|
buf |= (evenparity32((buf >> 13) & 0xFFF)) << 25;
|
||||||
|
|
||||||
uint32_t cardnumNew = (buf >> 1) & 0xFFFF;
|
uint32_t cardnumNew = (buf >> 1) & 0xFFFF;
|
||||||
uint32_t fcNew = (buf >> 17) & 0xFF;
|
uint32_t fcNew = (buf >> 17) & 0xFF;
|
||||||
|
@ -197,7 +202,6 @@ static uint64_t PackEmID(uint64_t original, int newCardNum) {
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void PrintFcAndCardNum(uint64_t lowData) {
|
static void PrintFcAndCardNum(uint64_t lowData) {
|
||||||
// Calculate Facility Code and Card Number from high and low
|
// Calculate Facility Code and Card Number from high and low
|
||||||
uint32_t fc = (lowData >> 17) & 0xFF;
|
uint32_t fc = (lowData >> 17) & 0xFF;
|
||||||
|
@ -222,7 +226,7 @@ static int BruteEMTag(uint64_t originalCard, int slot) {
|
||||||
cardnum = cardnum + direction;
|
cardnum = cardnum + direction;
|
||||||
uint64_t currentCard = PackEmID(originalCard, cardnum);
|
uint64_t currentCard = PackEmID(originalCard, cardnum);
|
||||||
Dbprintf("[=] >> Simulating card id %"PRIx64" <<", currentCard);
|
Dbprintf("[=] >> Simulating card id %"PRIx64" <<", currentCard);
|
||||||
ConstructEM410xEmulBuf(ReversQuads(currentCard));
|
construct_EM410x_emul(rev_quads(currentCard));
|
||||||
SimulateTagLowFrequencyEx(buflen, 0, 1, bruteforceSpeed[bruteforceSpeedCurrent] * 10000);
|
SimulateTagLowFrequencyEx(buflen, 0, 1, bruteforceSpeed[bruteforceSpeedCurrent] * 10000);
|
||||||
|
|
||||||
int button_pressed = BUTTON_CLICKED(1000);
|
int button_pressed = BUTTON_CLICKED(1000);
|
||||||
|
@ -267,7 +271,7 @@ static int ExecuteMode(int mode, int slot) {
|
||||||
return LF_RWSB_UNKNOWN_RESULT;
|
return LF_RWSB_UNKNOWN_RESULT;
|
||||||
case LF_RWSB_MODE_SIM:
|
case LF_RWSB_MODE_SIM:
|
||||||
Dbprintf("[=] >> Sim mode started <<");
|
Dbprintf("[=] >> Sim mode started <<");
|
||||||
ConstructEM410xEmulBuf(ReversQuads(low[slot]));
|
construct_EM410x_emul(rev_quads(low[slot]));
|
||||||
SimulateTagLowFrequency(buflen, 0, 1);
|
SimulateTagLowFrequency(buflen, 0, 1);
|
||||||
return LF_RWSB_UNKNOWN_RESULT;
|
return LF_RWSB_UNKNOWN_RESULT;
|
||||||
case LF_RWSB_MODE_WRITE:
|
case LF_RWSB_MODE_WRITE:
|
||||||
|
@ -310,7 +314,6 @@ void RunMod() {
|
||||||
int slot = 0;
|
int slot = 0;
|
||||||
mode = SwitchMode(mode, slot);
|
mode = SwitchMode(mode, slot);
|
||||||
|
|
||||||
bba = BigBuf_get_addr();
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (data_available()) break;
|
if (data_available()) break;
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
// In high[] must be nulls
|
// In high[] must be nulls
|
||||||
static uint64_t low[] = {0x565AF781C7, 0x540053E4E2, 0x1234567890, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
static uint64_t low[] = {0x565AF781C7, 0x540053E4E2, 0x1234567890, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
static uint32_t high[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
static uint32_t high[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
static uint8_t *bba, slots_count;
|
static uint8_t slots_count;
|
||||||
static int buflen;
|
static int buflen;
|
||||||
|
|
||||||
void ModInfo(void) {
|
void ModInfo(void) {
|
||||||
|
@ -56,7 +56,8 @@ static uint64_t rev_quads(uint64_t bits) {
|
||||||
return result >> 24;
|
return result >> 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fillbuff(uint8_t bit) {
|
static void fill_buff(uint8_t bit) {
|
||||||
|
uint8_t *bba = BigBuf_get_addr();
|
||||||
memset(bba + buflen, bit, LF_CLOCK / 2);
|
memset(bba + buflen, bit, LF_CLOCK / 2);
|
||||||
buflen += (LF_CLOCK / 2);
|
buflen += (LF_CLOCK / 2);
|
||||||
memset(bba + buflen, bit ^ 1, LF_CLOCK / 2);
|
memset(bba + buflen, bit ^ 1, LF_CLOCK / 2);
|
||||||
|
@ -66,29 +67,29 @@ static void fillbuff(uint8_t bit) {
|
||||||
static void construct_EM410x_emul(uint64_t id) {
|
static void construct_EM410x_emul(uint64_t id) {
|
||||||
|
|
||||||
int i, j;
|
int i, j;
|
||||||
int binary[4] = {0};
|
int binary[4] = {0, 0, 0, 0};
|
||||||
int parity[4] = {0};
|
int parity[4] = {0, 0, 0, 0};
|
||||||
buflen = 0;
|
buflen = 0;
|
||||||
|
|
||||||
for (i = 0; i < 9; i++)
|
for (i = 0; i < 9; i++)
|
||||||
fillbuff(1);
|
fill_buff(1);
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
for (j = 3; j >= 0; j--, id /= 2)
|
for (j = 3; j >= 0; j--, id /= 2)
|
||||||
binary[j] = id % 2;
|
binary[j] = id % 2;
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
fillbuff(binary[j]);
|
fill_buff(binary[j]);
|
||||||
|
|
||||||
fillbuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
fill_buff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
parity[j] ^= binary[j];
|
parity[j] ^= binary[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
fillbuff(parity[j]);
|
fill_buff(parity[j]);
|
||||||
|
|
||||||
fillbuff(0);
|
fill_buff(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void led_slot(int i) {
|
static void led_slot(int i) {
|
||||||
|
@ -138,7 +139,6 @@ void RunMod(void) {
|
||||||
// 3 - write to T5555 tag
|
// 3 - write to T5555 tag
|
||||||
uint8_t state = 0;
|
uint8_t state = 0;
|
||||||
slots_count = ARRAYLEN(low);
|
slots_count = ARRAYLEN(low);
|
||||||
bba = BigBuf_get_addr();
|
|
||||||
led_slot(selected);
|
led_slot(selected);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Tharexde, 2020
|
// tharexde, 2021
|
||||||
//
|
//
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
// 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
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
@ -8,10 +8,12 @@
|
||||||
// main code for EM4x50 simulator and collector aka THAREXDE
|
// main code for EM4x50 simulator and collector aka THAREXDE
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include "ticks.h"
|
||||||
#include "standalone.h"
|
#include "standalone.h"
|
||||||
#include "proxmark3_arm.h"
|
#include "proxmark3_arm.h"
|
||||||
#include "appmain.h"
|
#include "appmain.h"
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
|
#include "commonutil.h"
|
||||||
#include "fpgaloader.h"
|
#include "fpgaloader.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "dbprint.h"
|
#include "dbprint.h"
|
||||||
|
@ -19,68 +21,75 @@
|
||||||
#include "../em4x50.h"
|
#include "../em4x50.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* `lf_tharexde` simulates hardcoded words/blocks, reads words of standard read
|
* `lf_tharexde` simulates EM4x50 dumps uploaded to flash, reads words
|
||||||
* mode of EM4x50 tags and stores them in internal flash.
|
* transmitted by EM4x50 tags in standard read mode and stores them in
|
||||||
|
* internal flash.
|
||||||
* It requires RDV4 hardware (for flash and battery).
|
* It requires RDV4 hardware (for flash and battery).
|
||||||
*
|
*
|
||||||
* On entering stand-alone mode, this module will start reading/record EM4x50 data.
|
* On entering stand-alone mode, this module will start simulating EM4x50 data.
|
||||||
* Every found / collected data will be written/appended to the logfile in flash
|
* Data is read from eml dump file uploaded to flash memory (lf_em4x50_simulate.eml).
|
||||||
* as a text string.
|
* If reader sends password different from dump file password, it is saved in
|
||||||
|
* file lf_em4x50_passwords.log in flash memory.
|
||||||
|
*
|
||||||
|
* On switching to read/record mode by pressing pm3 button, module will start
|
||||||
|
* reading EM4x50 data. Each collected data set will be written/appended to the
|
||||||
|
* logfile in flash (lf_em4x50_collect.log) as a text string.
|
||||||
*
|
*
|
||||||
* LEDs:
|
* LEDs:
|
||||||
* - LED A: simulating
|
* - LED A: simulating
|
||||||
* - LED B: reading / record
|
* - LED A blinking: no simulation data or read error
|
||||||
* - LED C: writing to flash
|
* - LED B: reading/recording
|
||||||
* - LED D: unmounting/sync'ing flash (normally < 100ms)
|
* - LED D: unmounting/sync'ing flash (normally < 100ms)
|
||||||
*
|
*
|
||||||
|
* To upload input file (eml format) to flash:
|
||||||
|
* - mem spiffs load f <filename> o lf_em4x50_simulate.eml
|
||||||
|
*
|
||||||
|
* To retrieve password file from flash:
|
||||||
|
* - mem spiffs dump o lf_em4x50_passwords.log f <filename>
|
||||||
|
*
|
||||||
* To retrieve log file from flash:
|
* To retrieve log file from flash:
|
||||||
*
|
* - mem spiffs dump o lf_em4x50_collect.log f <filename>
|
||||||
* 1. mem spiffs dump o lf_em4x50collect.log f lf_em4x50collect.log
|
|
||||||
* Copies log file from flash to your client.
|
|
||||||
*
|
|
||||||
* 2. exit the Proxmark3 client
|
|
||||||
*
|
|
||||||
* 3. more lf_tharexdecollect.log
|
|
||||||
*
|
*
|
||||||
* This module emits debug strings during normal operation -- so try it out in
|
* 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.
|
* the lab connected to PM3 client before taking it into the field.
|
||||||
*
|
*
|
||||||
* To delete the log file from flash:
|
* To delete the input file from flash:
|
||||||
|
* - mem spiffs remove lf_em4x50_simulate.eml
|
||||||
*
|
*
|
||||||
* 1. mem spiffs remove lf_tharexdecollect.log
|
* To delete the log file from flash:
|
||||||
|
* - mem spiffs remove lf_em4x50_passwords.log
|
||||||
|
*
|
||||||
|
* To delete the log file from flash:
|
||||||
|
* - mem spiffs remove lf_em4x50_collect.log
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define STATE_SIM 0
|
#define STATE_SIM 0
|
||||||
#define STATE_READ 1
|
#define STATE_READ 1
|
||||||
#define STATE_BRUTE 2
|
#define LF_EM4X50_INPUTFILE_SIM "lf_em4x50_simulate.eml"
|
||||||
#define EM4X50_TAG_WORD 45
|
#define LF_EM4X50_LOGFILE_SIM "lf_em4x50_passwords.log"
|
||||||
#define EM4X50_PWD_SPEED 27
|
#define LF_EM4X50_LOGFILE_COLLECT "lf_em4x50_collect.log"
|
||||||
#define LF_EM4X50SIMULATE_INPUTFILE "lf_em4x50simulate.eml"
|
#define MAX_NO_PWDS_TO_SAVE 50
|
||||||
#define LF_EM4X50COLLECT_LOGFILE "lf_em4x50collect.log"
|
|
||||||
#define LF_EM4X50BRUTE_INPUTFILE "lf_em4x50brute.eml"
|
|
||||||
#define LF_EM4X50BRUTE_LOGFILE "lf_em4x50brute.log"
|
|
||||||
|
|
||||||
bool input_exists;
|
uint32_t gPassword;
|
||||||
bool log_exists;
|
|
||||||
|
|
||||||
static void LoadDataInstructions(const char *inputfile) {
|
static void LoadDataInstructions(const char *inputfile) {
|
||||||
Dbprintf("");
|
Dbprintf("");
|
||||||
Dbprintf("To load datafile into flash and display it:");
|
Dbprintf("To load datafile to flash and display it:");
|
||||||
Dbprintf(_YELLOW_("1.") " edit inputfile %s", inputfile);
|
Dbprintf("1. edit input file %s", inputfile);
|
||||||
Dbprintf(_YELLOW_("2.") " start proxmark3 client");
|
Dbprintf("2. start proxmark3 client");
|
||||||
Dbprintf(_YELLOW_("3.") " mem spiffs load f %s o %s", inputfile, inputfile);
|
Dbprintf("3. mem spiffs load f <filename> o %s", inputfile);
|
||||||
Dbprintf(_YELLOW_("4.") " start standalone mode");
|
Dbprintf("4. start standalone mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DownloadLogInstructions(const char *logfile) {
|
static void DownloadLogInstructions(const char *logfile) {
|
||||||
Dbprintf("");
|
Dbprintf("");
|
||||||
Dbprintf("To get the logfile from flash and display it:");
|
Dbprintf("To get the logfile from flash and display it:");
|
||||||
Dbprintf(_YELLOW_("1.") " mem spiffs dump o %s f %s", logfile, logfile);
|
Dbprintf("1. mem spiffs dump o %s f <filename>", logfile);
|
||||||
Dbprintf(_YELLOW_("2.") " exit proxmark3 client");
|
Dbprintf("2. exit proxmark3 client");
|
||||||
Dbprintf(_YELLOW_("3.") " cat %s", logfile);
|
Dbprintf("3. cat <filename>");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_input_data_from_file(uint32_t *words, char *inputfile) {
|
static bool get_input_data_from_file(uint32_t *tag, char *inputfile) {
|
||||||
|
|
||||||
size_t now = 0;
|
size_t now = 0;
|
||||||
|
|
||||||
|
@ -94,75 +103,77 @@ static int get_input_data_from_file(uint32_t *words, char *inputfile) {
|
||||||
rdv40_spiffs_read_as_filetype(inputfile, mem, size, RDV40_SPIFFS_SAFETY_SAFE);
|
rdv40_spiffs_read_as_filetype(inputfile, mem, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
|
|
||||||
now = size / 9;
|
now = size / 9;
|
||||||
for (int i = 0; i < now; i++)
|
for (int i = 0; i < now; i++) {
|
||||||
for (int j = 0; j < 4; j++)
|
for (int j = 0; j < 4; j++) {
|
||||||
words[i] |= (hex2int(mem[2 * j + 9 * i]) << 4 | hex2int(mem[2 * j + 1 + 9 * i])) << ((3 - j) * 8);
|
tag[i] |= (hex2int(mem[2 * j + 9 * i]) << 4 | hex2int(mem[2 * j + 1 + 9 * i])) << ((3 - j) * 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Dbprintf(_YELLOW_("read data from input file"));
|
Dbprintf(_YELLOW_("read tag data from input file"));
|
||||||
|
} else {
|
||||||
|
Dbprintf(_RED_("no input file %s"), inputfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
|
||||||
return (now > 0) ? now : 0;
|
return ((now == EM4X50_NO_WORDS) && (tag[EM4X50_DEVICE_SERIAL] != tag[EM4X50_DEVICE_ID]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void append(const char *filename, uint8_t *entry, size_t entry_len) {
|
static void append(const char *filename, uint8_t *entry, size_t entry_len) {
|
||||||
|
if (exists_in_spiffs(filename)) {
|
||||||
LED_D_ON();
|
|
||||||
if (log_exists == false) {
|
|
||||||
rdv40_spiffs_write(filename, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE);
|
|
||||||
log_exists = true;
|
|
||||||
} else {
|
|
||||||
rdv40_spiffs_append(filename, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE);
|
rdv40_spiffs_append(filename, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
|
} else {
|
||||||
|
rdv40_spiffs_write(filename, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void save_pwds(uint32_t *pwdlist, size_t no_pwd) {
|
||||||
|
uint8_t entry[10] = {0};
|
||||||
|
|
||||||
|
if (no_pwd > 0) {
|
||||||
|
Dbprintf("");
|
||||||
|
for (int i = 0; i < no_pwd; i++) {
|
||||||
|
sprintf((char *)entry, "%08"PRIx32"\n", pwdlist[i]);
|
||||||
|
append(LF_EM4X50_LOGFILE_SIM, entry, strlen((char *)entry));
|
||||||
|
Dbprintf("received password: %08"PRIx32"", pwdlist[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LED_D_OFF();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModInfo(void) {
|
void ModInfo(void) {
|
||||||
DbpString(_YELLOW_(" LF EM4x50 sim/collector/bruteforce mode") " - a.k.a tharexde");
|
DbpString(_YELLOW_(" LF EM4x50 sim/collector mode") " - a.k.a tharexde");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunMod(void) {
|
void RunMod(void) {
|
||||||
|
|
||||||
bool state_change = true;//, password_found = false;
|
bool state_change = true, read_ok = false;
|
||||||
int pwd_found = false;
|
int no_words = 0, command = 0, no_pwd = 0;
|
||||||
uint8_t state = STATE_SIM;
|
uint8_t entry[400], state = STATE_SIM;
|
||||||
// declarations for simulating
|
uint32_t tag[EM4X50_NO_WORDS] = {0x0}, pwdlist[MAX_NO_PWDS_TO_SAVE];
|
||||||
uint32_t words[33] = {0x0};
|
|
||||||
uint32_t pwd = 0x0;
|
|
||||||
uint32_t passwords[2] = {0x0};
|
|
||||||
size_t now = 0;
|
|
||||||
// declarations for reading
|
|
||||||
int no_words = 0;
|
|
||||||
//uint32_t words[EM4X50_TAG_WORD];
|
|
||||||
uint8_t entry[81];
|
|
||||||
|
|
||||||
rdv40_spiffs_lazy_mount();
|
rdv40_spiffs_lazy_mount();
|
||||||
|
|
||||||
StandAloneMode();
|
StandAloneMode();
|
||||||
Dbprintf(_YELLOW_("Standalone mode THAREXDE started"));
|
Dbprintf(_YELLOW_("Standalone mode THAREXDE started"));
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (data_available()) break;
|
if (data_available()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// press button - toggle between SIM, READ and BRUTE
|
// press button - toggle between SIM and READ
|
||||||
// hold button - exit
|
// hold button - exit
|
||||||
int button_pressed = BUTTON_CLICKED(1000);
|
int button_pressed = BUTTON_CLICKED(1000);
|
||||||
if (button_pressed == BUTTON_SINGLE_CLICK) {
|
if (button_pressed == BUTTON_SINGLE_CLICK) {
|
||||||
|
|
||||||
SpinUp(100);
|
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
|
||||||
case STATE_SIM:
|
case STATE_SIM:
|
||||||
|
// save and display passwords
|
||||||
|
save_pwds(pwdlist, no_pwd);
|
||||||
state = STATE_READ;
|
state = STATE_READ;
|
||||||
break;
|
break;
|
||||||
case STATE_READ:
|
case STATE_READ:
|
||||||
state = STATE_BRUTE;
|
|
||||||
break;
|
|
||||||
case STATE_BRUTE:
|
|
||||||
state = STATE_SIM;
|
state = STATE_SIM;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -172,8 +183,6 @@ void RunMod(void) {
|
||||||
state_change = true;
|
state_change = true;
|
||||||
|
|
||||||
} else if (button_pressed == BUTTON_HOLD) {
|
} else if (button_pressed == BUTTON_HOLD) {
|
||||||
|
|
||||||
SpinDown(100);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,170 +190,102 @@ void RunMod(void) {
|
||||||
|
|
||||||
if (state_change) {
|
if (state_change) {
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
// initialize simulation mode
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125);
|
|
||||||
|
|
||||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
|
|
||||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
|
||||||
AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
|
|
||||||
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
Dbprintf("");
|
Dbprintf("");
|
||||||
Dbprintf(_YELLOW_("switched to EM4x50 simulating mode"));
|
Dbprintf(_YELLOW_("switched to EM4x50 simulating mode"));
|
||||||
|
|
||||||
now = get_input_data_from_file(words, LF_EM4X50SIMULATE_INPUTFILE);
|
read_ok = get_input_data_from_file(tag, LF_EM4X50_INPUTFILE_SIM);
|
||||||
if (now > 0) {
|
if (read_ok) {
|
||||||
Dbprintf(_YELLOW_("simulating %i blocks"), now);
|
Dbprintf(_YELLOW_("tag data ok"));
|
||||||
for (int i = 0; i < now; i++)
|
|
||||||
Dbprintf("%2i -> %lx", i + 1, words[i]);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Dbprintf(_RED_("error in input data"));
|
Dbprintf(_RED_("error in tag data"));
|
||||||
|
LoadDataInstructions(LF_EM4X50_INPUTFILE_SIM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LED_D_OFF();
|
||||||
|
gLogin = false;
|
||||||
|
gPassword = reflect32(tag[0]);
|
||||||
|
gWritePasswordProcess = false;
|
||||||
|
command = EM4X50_COMMAND_STANDARD_READ;
|
||||||
|
no_pwd = 0;
|
||||||
|
memset(pwdlist, 0, sizeof(pwdlist));
|
||||||
|
|
||||||
|
em4x50_setup_sim();
|
||||||
state_change = false;
|
state_change = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
em4x50_sim_send_listen_window();
|
// if no data or read error -> blink
|
||||||
for (int i = 0; i < now; i++) {
|
if (read_ok == false) {
|
||||||
em4x50_sim_send_listen_window();
|
LED(LED_A, 200);
|
||||||
em4x50_sim_send_word(words[i]);
|
SpinDelay(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
em4x50_handle_commands(&command, tag);
|
||||||
|
|
||||||
|
// check if new password was found
|
||||||
|
if (gPassword != reflect32(tag[EM4X50_DEVICE_PASSWORD])) {
|
||||||
|
if (no_pwd < MAX_NO_PWDS_TO_SAVE) {
|
||||||
|
pwdlist[no_pwd] = gPassword;
|
||||||
|
no_pwd++;
|
||||||
|
}
|
||||||
|
gPassword = reflect32(tag[EM4X50_DEVICE_PASSWORD]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if timeout (e.g. no reader field) continue with standard read
|
||||||
|
// mode and reset former authentication
|
||||||
|
if (command == PM3_ETIMEOUT) {
|
||||||
|
command = EM4X50_COMMAND_STANDARD_READ;
|
||||||
|
gLogin = false;
|
||||||
|
LED_D_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (state == STATE_READ) {
|
} else if (state == STATE_READ) {
|
||||||
|
|
||||||
if (state_change) {
|
if (state_change) {
|
||||||
|
|
||||||
|
// initialize read mode
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
Dbprintf("");
|
Dbprintf("");
|
||||||
Dbprintf(_YELLOW_("switched to EM4x50 reading mode"));
|
Dbprintf(_YELLOW_("switched to EM4x50 reading mode"));
|
||||||
|
|
||||||
memset(entry, 0, sizeof(entry));
|
em4x50_setup_read();
|
||||||
memset(words, 0, sizeof(words));
|
|
||||||
|
|
||||||
log_exists = exists_in_spiffs(LF_EM4X50COLLECT_LOGFILE);
|
|
||||||
|
|
||||||
state_change = false;
|
state_change = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
no_words = em4x50_standalone_read(words);
|
no_words = 0;
|
||||||
|
memset(tag, 0, sizeof(tag));
|
||||||
|
standard_read(&no_words, tag);
|
||||||
|
|
||||||
if (no_words > 0) {
|
if (no_words > 0) {
|
||||||
|
|
||||||
memset(entry, 0, sizeof(entry));
|
memset(entry, 0, sizeof(entry));
|
||||||
|
|
||||||
sprintf((char *)entry, "found new EM4x50 tag:");
|
sprintf((char *)entry, "found EM4x50 tag:\n");
|
||||||
Dbprintf("%s", entry);
|
|
||||||
strcat((char *)entry, "\n");
|
|
||||||
append(LF_EM4X50COLLECT_LOGFILE, entry, strlen((char *)entry));
|
|
||||||
|
|
||||||
for (int i = 0; i < no_words; i++) {
|
for (int i = 0; i < no_words; i++) {
|
||||||
|
sprintf((char *)entry + strlen((char *)entry), "%08"PRIx32"\n", tag[i]);
|
||||||
sprintf((char *)entry, " %2i -> 0x%08"PRIx32"", i + 1, words[i]);
|
}
|
||||||
Dbprintf("%s", entry);
|
Dbprintf("%s", entry);
|
||||||
strcat((char *)entry, "\n");
|
sprintf((char *)entry + strlen((char *)entry), "\n");
|
||||||
append(LF_EM4X50COLLECT_LOGFILE, entry, strlen((char *)entry));
|
append(LF_EM4X50_LOGFILE_COLLECT, entry, strlen((char *)entry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (state == STATE_BRUTE) {
|
// reset timer
|
||||||
|
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // re-enable timer and wait for TC0
|
||||||
if (state_change) {
|
AT91C_BASE_TC0->TC_RC = 0; // set TIOA (carry bit) on overflow, return to zero
|
||||||
|
AT91C_BASE_TC0->TC_RA = 1; // clear carry bit on next clock cycle
|
||||||
LEDsoff();
|
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // reset and re-enable timer
|
||||||
LED_C_ON();
|
|
||||||
Dbprintf("");
|
|
||||||
Dbprintf(_YELLOW_("switched to EM4x50 brute force mode"));
|
|
||||||
|
|
||||||
log_exists = exists_in_spiffs(LF_EM4X50BRUTE_LOGFILE);
|
|
||||||
now = get_input_data_from_file(passwords, LF_EM4X50BRUTE_INPUTFILE);
|
|
||||||
|
|
||||||
if (now == 2) {
|
|
||||||
|
|
||||||
// print some information
|
|
||||||
int no_iter = passwords[1] - passwords[0] + 1;
|
|
||||||
int dur_s = no_iter / EM4X50_PWD_SPEED;
|
|
||||||
int dur_h = dur_s / 3600;
|
|
||||||
int dur_m = (dur_s - dur_h * 3600) / 60;
|
|
||||||
dur_s -= dur_h * 3600 + dur_m * 60;
|
|
||||||
|
|
||||||
//iterprint = no_iter/10;
|
|
||||||
|
|
||||||
Dbprintf(_YELLOW_("trying %i passwords in range [0x%08x, 0x%08x]"),
|
|
||||||
no_iter, passwords[0], passwords[1]);
|
|
||||||
Dbprintf(_YELLOW_("estimated duration: %ih%im%is"),
|
|
||||||
dur_h, dur_m, dur_s);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Dbprintf(_RED_("error in input data"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
state_change = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pwd_found = em4x50_standalone_brute(passwords[0], passwords[1], &pwd);
|
|
||||||
|
|
||||||
if (pwd_found == PM3_ETIMEOUT) {
|
|
||||||
|
|
||||||
// timeout -> no EM4x50 tag on reader?
|
|
||||||
Dbprintf(_YELLOW_("timeout - no EM4x50 tag detected"));
|
|
||||||
|
|
||||||
} else if (pwd_found == true) {
|
|
||||||
|
|
||||||
// password found -> write to logfile
|
|
||||||
sprintf((char *)entry, "password found: 0x%08"PRIx32, pwd);
|
|
||||||
Dbprintf(_YELLOW_("%s"), entry);
|
|
||||||
strcat((char *)entry, "\n");
|
|
||||||
append(LF_EM4X50BRUTE_LOGFILE, entry, strlen((char *)entry));
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (pwd == passwords[1] + 1) {
|
|
||||||
|
|
||||||
// finished without success -> write to logfile
|
|
||||||
sprintf((char *)entry, "no password found");
|
|
||||||
Dbprintf(_YELLOW_("%s"), entry);
|
|
||||||
strcat((char *)entry, "\n");
|
|
||||||
append(LF_EM4X50BRUTE_LOGFILE, entry, strlen((char *)entry));
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// stopped -> write to logfile
|
|
||||||
sprintf((char *)entry, "stopped search - last password: 0x%08"PRIx32, pwd);
|
|
||||||
Dbprintf(_YELLOW_("%s"), entry);
|
|
||||||
strcat((char *)entry, "\n");
|
|
||||||
append(LF_EM4X50BRUTE_LOGFILE, entry, strlen((char *)entry));
|
|
||||||
|
|
||||||
// replace start password by last tested password in
|
|
||||||
// inputfile (spiffs) so that brute forcing process will
|
|
||||||
// be continued when envoking brute force mode again
|
|
||||||
sprintf((char *)entry, "%08"PRIx32"\n%08"PRIx32"\n", pwd, passwords[1]);
|
|
||||||
rdv40_spiffs_write(LF_EM4X50BRUTE_INPUTFILE,
|
|
||||||
entry,
|
|
||||||
strlen((char *)entry),
|
|
||||||
RDV40_SPIFFS_SAFETY_SAFE);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == STATE_READ) {
|
if (state == STATE_READ) {
|
||||||
DownloadLogInstructions(LF_EM4X50COLLECT_LOGFILE);
|
DownloadLogInstructions(LF_EM4X50_LOGFILE_COLLECT);
|
||||||
} else if (state == STATE_BRUTE) {
|
|
||||||
LoadDataInstructions(LF_EM4X50BRUTE_INPUTFILE);
|
|
||||||
DownloadLogInstructions(LF_EM4X50BRUTE_LOGFILE);
|
|
||||||
} else {
|
} else {
|
||||||
LoadDataInstructions(LF_EM4X50SIMULATE_INPUTFILE);
|
// save and display passwords
|
||||||
|
save_pwds(pwdlist, no_pwd);
|
||||||
|
DownloadLogInstructions(LF_EM4X50_LOGFILE_SIM);
|
||||||
}
|
}
|
||||||
|
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
|
@ -352,8 +293,8 @@ void RunMod(void) {
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
Dbprintf("");
|
Dbprintf("");
|
||||||
Dbprintf(_YELLOW_("[=] Standalone mode THAREXDE stopped"));
|
Dbprintf(_YELLOW_("[=] Standalone mode THAREXDE stopped"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
|
|
||||||
#ifdef WITH_LCD
|
#ifdef WITH_LCD
|
||||||
#include "LCD.h"
|
#include "LCD_disabled.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_SMARTCARD
|
#ifdef WITH_SMARTCARD
|
||||||
|
@ -257,6 +257,9 @@ void ReadMem(int addr) {
|
||||||
/* osimage version information is linked in, cf commonutil.h */
|
/* osimage version information is linked in, cf commonutil.h */
|
||||||
/* bootrom version information is pointed to from _bootphase1_version_pointer */
|
/* bootrom version information is pointed to from _bootphase1_version_pointer */
|
||||||
extern char *_bootphase1_version_pointer, _flash_start, _flash_end, __data_src_start__;
|
extern char *_bootphase1_version_pointer, _flash_start, _flash_end, __data_src_start__;
|
||||||
|
#ifdef WITH_NO_COMPRESSION
|
||||||
|
extern char *_bootrom_end, _bootrom_start, __os_size__;
|
||||||
|
#endif
|
||||||
static void SendVersion(void) {
|
static void SendVersion(void) {
|
||||||
char temp[PM3_CMD_DATA_SIZE - 12]; /* Limited data payload in USB packets */
|
char temp[PM3_CMD_DATA_SIZE - 12]; /* Limited data payload in USB packets */
|
||||||
char VersionString[PM3_CMD_DATA_SIZE - 12] = { '\0' };
|
char VersionString[PM3_CMD_DATA_SIZE - 12] = { '\0' };
|
||||||
|
@ -295,9 +298,11 @@ static void SendVersion(void) {
|
||||||
strncat(VersionString, "\n ", sizeof(VersionString) - strlen(VersionString) - 1);
|
strncat(VersionString, "\n ", sizeof(VersionString) - strlen(VersionString) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifndef WITH_NO_COMPRESSION
|
||||||
// Send Chip ID and used flash memory
|
// Send Chip ID and used flash memory
|
||||||
uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
|
uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
|
||||||
uint32_t compressed_data_section_size = common_area.arg1;
|
uint32_t compressed_data_section_size = common_area.arg1;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct p {
|
struct p {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
@ -308,7 +313,11 @@ static void SendVersion(void) {
|
||||||
|
|
||||||
struct p payload;
|
struct p payload;
|
||||||
payload.id = *(AT91C_DBGU_CIDR);
|
payload.id = *(AT91C_DBGU_CIDR);
|
||||||
|
#ifdef WITH_NO_COMPRESSION
|
||||||
|
payload.section_size = (uint32_t)&_bootrom_end - (uint32_t)&_bootrom_start + (uint32_t)&__os_size__;
|
||||||
|
#else
|
||||||
payload.section_size = text_and_rodata_section_size + compressed_data_section_size;
|
payload.section_size = text_and_rodata_section_size + compressed_data_section_size;
|
||||||
|
#endif
|
||||||
payload.versionstr_len = strlen(VersionString) + 1;
|
payload.versionstr_len = strlen(VersionString) + 1;
|
||||||
memcpy(payload.versionstr, VersionString, payload.versionstr_len);
|
memcpy(payload.versionstr, VersionString, payload.versionstr_len);
|
||||||
|
|
||||||
|
@ -1136,7 +1145,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
// destroy the Emulator Memory.
|
// destroy the Emulator Memory.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
em4x50_sim((uint8_t *)packet->data.asBytes);
|
em4x50_sim((uint32_t *)packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_LF_EM4X50_READER: {
|
case CMD_LF_EM4X50_READER: {
|
||||||
|
@ -1170,6 +1179,26 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
em4x70_info((em4x70_data_t *)packet->data.asBytes);
|
em4x70_info((em4x70_data_t *)packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CMD_LF_EM4X70_WRITE: {
|
||||||
|
em4x70_write((em4x70_data_t *)packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_LF_EM4X70_UNLOCK: {
|
||||||
|
em4x70_unlock((em4x70_data_t *)packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_LF_EM4X70_AUTH: {
|
||||||
|
em4x70_auth((em4x70_data_t *)packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_LF_EM4X70_WRITEPIN: {
|
||||||
|
em4x70_write_pin((em4x70_data_t *)packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_LF_EM4X70_WRITEKEY: {
|
||||||
|
em4x70_write_key((em4x70_data_t *)packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_ISO15693
|
#ifdef WITH_ISO15693
|
||||||
|
@ -1637,10 +1666,6 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
iClass_ReadBlock(packet->data.asBytes);
|
iClass_ReadBlock(packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_ICLASS_AUTH: { //check
|
|
||||||
iClass_Authentication(packet->data.asBytes);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CMD_HF_ICLASS_CHKKEYS: {
|
case CMD_HF_ICLASS_CHKKEYS: {
|
||||||
iClass_Authentication_fast(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
iClass_Authentication_fast(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -242,7 +242,6 @@ void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfire
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xor(const uint8_t *ivect, uint8_t *data, const size_t len);
|
|
||||||
static size_t key_macing_length(desfirekey_t key);
|
static size_t key_macing_length(desfirekey_t key);
|
||||||
|
|
||||||
// iceman, see memxor inside string.c, dest/src swapped..
|
// iceman, see memxor inside string.c, dest/src swapped..
|
||||||
|
@ -264,20 +263,20 @@ void cmac_generate_subkeys(desfirekey_t key) {
|
||||||
|
|
||||||
mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
|
mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
|
||||||
|
|
||||||
bool xor = false;
|
bool txor = false;
|
||||||
|
|
||||||
// Used to compute CMAC on complete blocks
|
// Used to compute CMAC on complete blocks
|
||||||
memcpy(key->cmac_sk1, l, kbs);
|
memcpy(key->cmac_sk1, l, kbs);
|
||||||
xor = l[0] & 0x80;
|
txor = l[0] & 0x80;
|
||||||
lsl(key->cmac_sk1, kbs);
|
lsl(key->cmac_sk1, kbs);
|
||||||
if (xor)
|
if (txor)
|
||||||
key->cmac_sk1[kbs - 1] ^= R;
|
key->cmac_sk1[kbs - 1] ^= R;
|
||||||
|
|
||||||
// Used to compute CMAC on the last block if non-complete
|
// Used to compute CMAC on the last block if non-complete
|
||||||
memcpy(key->cmac_sk2, key->cmac_sk1, kbs);
|
memcpy(key->cmac_sk2, key->cmac_sk1, kbs);
|
||||||
xor = key->cmac_sk1[0] & 0x80;
|
txor = key->cmac_sk1[0] & 0x80;
|
||||||
lsl(key->cmac_sk2, kbs);
|
lsl(key->cmac_sk2, kbs);
|
||||||
if (xor)
|
if (txor)
|
||||||
key->cmac_sk2[kbs - 1] ^= R;
|
key->cmac_sk2[kbs - 1] ^= R;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1158
armsrc/em4x50.c
1158
armsrc/em4x50.c
File diff suppressed because it is too large
Load diff
|
@ -13,10 +13,11 @@
|
||||||
|
|
||||||
#include "../include/em4x50.h"
|
#include "../include/em4x50.h"
|
||||||
|
|
||||||
int em4x50_standalone_read(uint32_t *words);
|
void em4x50_setup_read(void);
|
||||||
int em4x50_standalone_brute(uint32_t start, uint32_t stop, uint32_t *pwd);
|
int standard_read(int *now, uint32_t *words);
|
||||||
bool em4x50_sim_send_listen_window(void);
|
|
||||||
bool em4x50_sim_send_word(uint32_t word);
|
void em4x50_setup_sim(void);
|
||||||
|
void em4x50_handle_commands(int *command, uint32_t *tag);
|
||||||
|
|
||||||
void em4x50_info(em4x50_data_t *etd);
|
void em4x50_info(em4x50_data_t *etd);
|
||||||
void em4x50_write(em4x50_data_t *etd);
|
void em4x50_write(em4x50_data_t *etd);
|
||||||
|
@ -24,7 +25,7 @@ void em4x50_writepwd(em4x50_data_t *etd);
|
||||||
void em4x50_read(em4x50_data_t *etd);
|
void em4x50_read(em4x50_data_t *etd);
|
||||||
void em4x50_brute(em4x50_data_t *etd);
|
void em4x50_brute(em4x50_data_t *etd);
|
||||||
void em4x50_login(uint32_t *password);
|
void em4x50_login(uint32_t *password);
|
||||||
void em4x50_sim(uint8_t *filename);
|
void em4x50_sim(uint32_t *password);
|
||||||
void em4x50_reader(void);
|
void em4x50_reader(void);
|
||||||
void em4x50_chk(uint8_t *filename);
|
void em4x50_chk(uint8_t *filename);
|
||||||
|
|
||||||
|
|
722
armsrc/em4x70.c
722
armsrc/em4x70.c
|
@ -21,28 +21,35 @@ static em4x70_tag_t tag = { 0 };
|
||||||
// EM4170 requires a parity bit on commands, other variants do not.
|
// EM4170 requires a parity bit on commands, other variants do not.
|
||||||
static bool command_parity = true;
|
static bool command_parity = true;
|
||||||
|
|
||||||
#define EM4X70_T_TAG_QUARTER_PERIOD 8
|
// Conversion from Ticks to RF periods
|
||||||
#define EM4X70_T_TAG_HALF_PERIOD 16
|
// 1 us = 1.5 ticks
|
||||||
#define EM4X70_T_TAG_THREE_QUARTER_PERIOD 24
|
// 1RF Period = 8us = 12 Ticks
|
||||||
#define EM4X70_T_TAG_FULL_PERIOD 32
|
#define TICKS_PER_FC 12
|
||||||
#define EM4X70_T_TAG_TWA 128 // Write Access Time
|
|
||||||
#define EM4X70_T_TAG_DIV 224 // Divergency Time
|
|
||||||
#define EM4X70_T_TAG_AUTH 4224 // Authentication Time
|
|
||||||
#define EM4X70_T_TAG_WEE 3072 // EEPROM write Time
|
|
||||||
#define EM4X70_T_TAG_TWALB 128 // Write Access Time of Lock Bits
|
|
||||||
|
|
||||||
#define EM4X70_T_WAITING_FOR_SNGLLIW 160 // Unsure
|
// Chip timing from datasheet
|
||||||
|
// Converted into Ticks for timing functions
|
||||||
|
#define EM4X70_T_TAG_QUARTER_PERIOD (8 * TICKS_PER_FC)
|
||||||
|
#define EM4X70_T_TAG_HALF_PERIOD (16 * TICKS_PER_FC)
|
||||||
|
#define EM4X70_T_TAG_THREE_QUARTER_PERIOD (24 * TICKS_PER_FC)
|
||||||
|
#define EM4X70_T_TAG_FULL_PERIOD (32 * TICKS_PER_FC) // 1 Bit Period
|
||||||
|
#define EM4X70_T_TAG_TWA (128 * TICKS_PER_FC) // Write Access Time
|
||||||
|
#define EM4X70_T_TAG_DIV (224 * TICKS_PER_FC) // Divergency Time
|
||||||
|
#define EM4X70_T_TAG_AUTH (4224 * TICKS_PER_FC) // Authentication Time
|
||||||
|
#define EM4X70_T_TAG_WEE (3072 * TICKS_PER_FC) // EEPROM write Time
|
||||||
|
#define EM4X70_T_TAG_TWALB (672 * TICKS_PER_FC) // Write Access Time of Lock Bits
|
||||||
|
#define EM4X70_T_TAG_BITMOD (4 * TICKS_PER_FC) // Initial time to stop modulation when sending 0
|
||||||
|
#define EM4X70_T_TAG_TOLERANCE (8 * TICKS_PER_FC) // Tolerance in RF periods for receive/LIW
|
||||||
|
|
||||||
#define TICKS_PER_FC 12 // 1 fc = 8us, 1.5us per tick = 12 ticks
|
#define EM4X70_T_TAG_TIMEOUT (4 * EM4X70_T_TAG_FULL_PERIOD) // Timeout if we ever get a pulse longer than this
|
||||||
#define EM4X70_MIN_AMPLITUDE 10 // Minimum difference between a high and low signal
|
#define EM4X70_T_WAITING_FOR_LIW 50 // Pulses to wait for listen window
|
||||||
|
#define EM4X70_T_READ_HEADER_LEN 16 // Read header length (16 bit periods)
|
||||||
#define EM4X70_TAG_TOLERANCE 10
|
|
||||||
#define EM4X70_TAG_WORD 48
|
|
||||||
|
|
||||||
|
#define EM4X70_COMMAND_RETRIES 5 // Attempts to send/read command
|
||||||
|
#define EM4X70_MAX_RECEIVE_LENGTH 96 // Maximum bits to expect from any command
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These IDs are from the EM4170 datasheet
|
* These IDs are from the EM4170 datasheet
|
||||||
* Some versions of the chip require a fourth
|
* Some versions of the chip require a
|
||||||
* (even) parity bit, others do not
|
* (even) parity bit, others do not
|
||||||
*/
|
*/
|
||||||
#define EM4X70_COMMAND_ID 0x01
|
#define EM4X70_COMMAND_ID 0x01
|
||||||
|
@ -52,24 +59,28 @@ static bool command_parity = true;
|
||||||
#define EM4X70_COMMAND_WRITE 0x05
|
#define EM4X70_COMMAND_WRITE 0x05
|
||||||
#define EM4X70_COMMAND_UM2 0x07
|
#define EM4X70_COMMAND_UM2 0x07
|
||||||
|
|
||||||
static uint8_t gHigh = 0;
|
// Constants used to determing high/low state of signal
|
||||||
static uint8_t gLow = 0;
|
#define EM4X70_NOISE_THRESHOLD 13 // May depend on noise in environment
|
||||||
|
#define HIGH_SIGNAL_THRESHOLD (127 + EM4X70_NOISE_THRESHOLD)
|
||||||
|
#define LOW_SIGNAL_THRESHOLD (127 - EM4X70_NOISE_THRESHOLD)
|
||||||
|
|
||||||
#define IS_HIGH(sample) (sample>gLow ? true : false)
|
#define IS_HIGH(sample) (sample > LOW_SIGNAL_THRESHOLD ? true : false)
|
||||||
#define IS_LOW(sample) (sample<gHigh ? true : false)
|
#define IS_LOW(sample) (sample < HIGH_SIGNAL_THRESHOLD ? true : false)
|
||||||
|
|
||||||
|
// Timing related macros
|
||||||
#define IS_TIMEOUT(timeout_ticks) (GetTicks() > timeout_ticks)
|
#define IS_TIMEOUT(timeout_ticks) (GetTicks() > timeout_ticks)
|
||||||
|
#define TICKS_ELAPSED(start_ticks) (GetTicks() - start_ticks)
|
||||||
|
|
||||||
|
static uint8_t bits2byte(const uint8_t *bits, int length);
|
||||||
static uint8_t bits2byte(uint8_t *bits, int length);
|
static void bits2bytes(const uint8_t *bits, int length, uint8_t *out);
|
||||||
static void bits2bytes(uint8_t *bits, int length, uint8_t *out);
|
static int em4x70_receive(uint8_t *bits, size_t length);
|
||||||
static int em4x70_receive(uint8_t *bits);
|
|
||||||
static bool find_listen_window(bool command);
|
static bool find_listen_window(bool command);
|
||||||
|
|
||||||
static void init_tag(void) {
|
static void init_tag(void) {
|
||||||
memset(tag.data, 0x00, sizeof(tag.data)/sizeof(tag.data[0]));
|
memset(tag.data, 0x00, sizeof(tag.data) / sizeof(tag.data[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EM4170_setup_read(void) {
|
static void em4x70_setup_read(void) {
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||||
|
@ -102,208 +113,312 @@ static void EM4170_setup_read(void) {
|
||||||
|
|
||||||
static bool get_signalproperties(void) {
|
static bool get_signalproperties(void) {
|
||||||
|
|
||||||
// calculate signal properties (mean amplitudes) from measured data:
|
// Simple check to ensure we see a signal above the noise threshold
|
||||||
// 32 amplitudes (maximum values) -> mean amplitude value -> gHigh -> gLow
|
uint32_t no_periods = 32;
|
||||||
bool signal_found = false;
|
|
||||||
int no_periods = 32, pct = 50, noise = 140; // pct originally 75, found 50 was working better for me
|
|
||||||
uint8_t sample_ref = 127;
|
|
||||||
uint8_t sample_max_mean = 0;
|
|
||||||
uint8_t sample_max[no_periods];
|
|
||||||
uint32_t sample_max_sum = 0;
|
|
||||||
|
|
||||||
memset(sample_max, 0x00, sizeof(sample_max));
|
|
||||||
|
|
||||||
// wait until signal/noise > 1 (max. 32 periods)
|
// wait until signal/noise > 1 (max. 32 periods)
|
||||||
for (int i = 0; i < TICKS_PER_FC * EM4X70_T_TAG_FULL_PERIOD * no_periods; i++) {
|
for (int i = 0; i < EM4X70_T_TAG_FULL_PERIOD * no_periods; i++) {
|
||||||
|
|
||||||
// about 2 samples per bit period
|
// about 2 samples per bit period
|
||||||
WaitTicks(TICKS_PER_FC * EM4X70_T_TAG_HALF_PERIOD);
|
WaitTicks(EM4X70_T_TAG_HALF_PERIOD);
|
||||||
|
|
||||||
if (AT91C_BASE_SSC->SSC_RHR > noise) {
|
if (AT91C_BASE_SSC->SSC_RHR > HIGH_SIGNAL_THRESHOLD) {
|
||||||
signal_found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signal_found == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// calculate mean maximum value of 32 periods, each period has a length of
|
|
||||||
// 3 single "full periods" to eliminate the influence of a listen window
|
|
||||||
for (int i = 0; i < no_periods; i++) {
|
|
||||||
|
|
||||||
uint32_t start_ticks = GetTicks();
|
|
||||||
//AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
|
||||||
while (GetTicks() - start_ticks < TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD) {
|
|
||||||
|
|
||||||
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
|
|
||||||
if (sample > sample_max[i])
|
|
||||||
sample_max[i] = sample;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sample_max_sum += sample_max[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
sample_max_mean = sample_max_sum / no_periods;
|
|
||||||
|
|
||||||
// set global envelope variables
|
|
||||||
gHigh = sample_ref + pct * (sample_max_mean - sample_ref) / 100;
|
|
||||||
gLow = sample_ref - pct * (sample_max_mean - sample_ref) / 100;
|
|
||||||
|
|
||||||
// Basic sanity check
|
|
||||||
if(gHigh - gLow < EM4X70_MIN_AMPLITUDE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbprintf("%s: gHigh %d gLow: %d", __func__, gHigh, gLow);
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get_pulse_length
|
* get_falling_pulse_length
|
||||||
*
|
*
|
||||||
* Times falling edge pulses
|
* Returns time between falling edge pulse in ticks
|
||||||
*/
|
*/
|
||||||
static uint32_t get_pulse_length(void) {
|
static uint32_t get_falling_pulse_length(void) {
|
||||||
|
|
||||||
uint8_t sample;
|
uint32_t timeout = GetTicks() + EM4X70_T_TAG_TIMEOUT;
|
||||||
uint32_t timeout = GetTicks() + (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
|
||||||
|
|
||||||
do {
|
while (IS_HIGH(AT91C_BASE_SSC->SSC_RHR) && !IS_TIMEOUT(timeout));
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
}while (IS_HIGH(sample) && !IS_TIMEOUT(timeout));
|
|
||||||
|
|
||||||
if (IS_TIMEOUT(timeout))
|
if (IS_TIMEOUT(timeout))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint32_t start_ticks = GetTicks();
|
uint32_t start_ticks = GetTicks();
|
||||||
timeout = start_ticks + (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
|
||||||
|
|
||||||
do {
|
while (IS_LOW(AT91C_BASE_SSC->SSC_RHR) && !IS_TIMEOUT(timeout));
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
}while (IS_LOW(sample) && !IS_TIMEOUT(timeout));
|
|
||||||
|
|
||||||
if (IS_TIMEOUT(timeout))
|
if (IS_TIMEOUT(timeout))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
timeout = (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD) + GetTicks();
|
while (IS_HIGH(AT91C_BASE_SSC->SSC_RHR) && !IS_TIMEOUT(timeout));
|
||||||
do {
|
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
}while (IS_HIGH(sample) && !IS_TIMEOUT(timeout));
|
|
||||||
|
|
||||||
if (IS_TIMEOUT(timeout))
|
if (IS_TIMEOUT(timeout))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return GetTicks() - start_ticks;
|
return TICKS_ELAPSED(start_ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get_pulse_invert_length
|
* get_rising_pulse_length
|
||||||
*
|
*
|
||||||
* Times rising edge pules
|
* Returns time between rising edge pulse in ticks
|
||||||
* TODO: convert to single function with get_pulse_length()
|
|
||||||
*/
|
*/
|
||||||
static uint32_t get_pulse_invert_length(void) {
|
static uint32_t get_rising_pulse_length(void) {
|
||||||
|
|
||||||
uint8_t sample;
|
uint32_t timeout = GetTicks() + EM4X70_T_TAG_TIMEOUT;
|
||||||
uint32_t timeout = GetTicks() + (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
|
||||||
|
|
||||||
do {
|
while (IS_LOW(AT91C_BASE_SSC->SSC_RHR) && !IS_TIMEOUT(timeout));
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
}while (IS_LOW(sample) && !IS_TIMEOUT(timeout));
|
|
||||||
|
|
||||||
if (IS_TIMEOUT(timeout))
|
if (IS_TIMEOUT(timeout))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint32_t start_ticks = GetTicks();
|
uint32_t start_ticks = GetTicks();
|
||||||
timeout = start_ticks + (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
|
||||||
|
|
||||||
do {
|
while (IS_HIGH(AT91C_BASE_SSC->SSC_RHR) && !IS_TIMEOUT(timeout));
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
}while (IS_HIGH(sample) && !IS_TIMEOUT(timeout));
|
|
||||||
|
|
||||||
if (IS_TIMEOUT(timeout))
|
if (IS_TIMEOUT(timeout))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
timeout = GetTicks() + (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
while (IS_LOW(AT91C_BASE_SSC->SSC_RHR) && !IS_TIMEOUT(timeout));
|
||||||
do {
|
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
}while (IS_LOW(sample) && !IS_TIMEOUT(timeout));
|
|
||||||
|
|
||||||
if (IS_TIMEOUT(timeout))
|
if (IS_TIMEOUT(timeout))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return GetTicks() - start_ticks;
|
return TICKS_ELAPSED(start_ticks);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_pulse_length(uint32_t pl, int length, int margin) {
|
static uint32_t get_pulse_length(edge_detection_t edge) {
|
||||||
|
|
||||||
|
if (edge == RISING_EDGE)
|
||||||
|
return get_rising_pulse_length();
|
||||||
|
else if (edge == FALLING_EDGE)
|
||||||
|
return get_falling_pulse_length();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool check_pulse_length(uint32_t pl, uint32_t length) {
|
||||||
// check if pulse length <pl> corresponds to given length <length>
|
// check if pulse length <pl> corresponds to given length <length>
|
||||||
//Dbprintf("%s: pulse length %d vs %d", __func__, pl, length * TICKS_PER_FC);
|
return ((pl >= (length - EM4X70_T_TAG_TOLERANCE)) && (pl <= (length + EM4X70_T_TAG_TOLERANCE)));
|
||||||
return ((pl >= TICKS_PER_FC * (length - margin)) & (pl <= TICKS_PER_FC * (length + margin)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void em4x70_send_bit(int bit) {
|
static void em4x70_send_bit(bool bit) {
|
||||||
|
|
||||||
// send single bit according to EM4170 application note and datasheet
|
// send single bit according to EM4170 application note and datasheet
|
||||||
|
|
||||||
uint32_t start_ticks = GetTicks();
|
uint32_t start_ticks = GetTicks();
|
||||||
|
|
||||||
if (bit == 0) {
|
if (bit == 0) {
|
||||||
|
|
||||||
// disable modulation (drop the field) for 4 cycles of carrier
|
// disable modulation (drop the field) n cycles of carrier
|
||||||
LOW(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
while (GetTicks() - start_ticks <= TICKS_PER_FC * 4);
|
while (TICKS_ELAPSED(start_ticks) <= EM4X70_T_TAG_BITMOD);
|
||||||
|
|
||||||
// enable modulation (activates the field) for remaining first
|
// enable modulation (activates the field) for remaining first
|
||||||
// half of bit period
|
// half of bit period
|
||||||
HIGH(GPIO_SSC_DOUT);
|
HIGH(GPIO_SSC_DOUT);
|
||||||
while (GetTicks() - start_ticks <= TICKS_PER_FC * EM4X70_T_TAG_HALF_PERIOD);
|
while (TICKS_ELAPSED(start_ticks) <= EM4X70_T_TAG_HALF_PERIOD);
|
||||||
|
|
||||||
// disable modulation for second half of bit period
|
// disable modulation for second half of bit period
|
||||||
LOW(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
while (GetTicks() - start_ticks <= TICKS_PER_FC * EM4X70_T_TAG_FULL_PERIOD);
|
while (TICKS_ELAPSED(start_ticks) <= EM4X70_T_TAG_FULL_PERIOD);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// bit = "1" means disable modulation for full bit period
|
// bit = "1" means disable modulation for full bit period
|
||||||
LOW(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
while (GetTicks() - start_ticks <= TICKS_PER_FC * EM4X70_T_TAG_FULL_PERIOD);
|
while (TICKS_ELAPSED(start_ticks) <= EM4X70_T_TAG_FULL_PERIOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* em4x70_send_command
|
* em4x70_send_nibble
|
||||||
|
*
|
||||||
|
* sends 4 bits of data + 1 bit of parity (with_parity)
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
static void em4170_send_command(uint8_t command) {
|
static void em4x70_send_nibble(uint8_t nibble, bool with_parity) {
|
||||||
int parity = 0;
|
int parity = 0;
|
||||||
int msb_bit = 0;
|
int msb_bit = 0;
|
||||||
|
|
||||||
// Non automotive EM4x70 based tags are 3 bits + 1 parity.
|
// Non automotive EM4x70 based tags are 3 bits + 1 parity.
|
||||||
// So drop the MSB and send a parity bit instead after the command
|
// So drop the MSB and send a parity bit instead after the command
|
||||||
if(command_parity)
|
if (command_parity)
|
||||||
msb_bit = 1;
|
msb_bit = 1;
|
||||||
|
|
||||||
for (int i = msb_bit; i < 4; i++) {
|
for (int i = msb_bit; i < 4; i++) {
|
||||||
int bit = (command >> (3 - i)) & 1;
|
int bit = (nibble >> (3 - i)) & 1;
|
||||||
em4x70_send_bit(bit);
|
em4x70_send_bit(bit);
|
||||||
parity ^= bit;
|
parity ^= bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(command_parity)
|
if (with_parity)
|
||||||
em4x70_send_bit(parity);
|
em4x70_send_bit(parity);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void em4x70_send_byte(uint8_t byte) {
|
||||||
|
// Send byte msb first
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
em4x70_send_bit((byte >> (7 - i)) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void em4x70_send_word(const uint16_t word) {
|
||||||
|
|
||||||
|
// Split into nibbles
|
||||||
|
uint8_t nibbles[4];
|
||||||
|
uint8_t j = 0;
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
uint8_t byte = (word >> (8 * i)) & 0xff;
|
||||||
|
nibbles[j++] = (byte >> 4) & 0xf;
|
||||||
|
nibbles[j++] = byte & 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send 16 bit word with parity bits according to EM4x70 datasheet
|
||||||
|
// sent as 4 x nibbles (4 bits + parity)
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
em4x70_send_nibble(nibbles[i], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send column parities (4 bit)
|
||||||
|
em4x70_send_nibble(nibbles[0] ^ nibbles[1] ^ nibbles[2] ^ nibbles[3], false);
|
||||||
|
|
||||||
|
// send final stop bit (always "0")
|
||||||
|
em4x70_send_bit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool check_ack(void) {
|
||||||
|
// returns true if signal structue corresponds to ACK, anything else is
|
||||||
|
// counted as NAK (-> false)
|
||||||
|
// ACK 64 + 64
|
||||||
|
// NACK 64 + 48
|
||||||
|
if (check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD) &&
|
||||||
|
check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD)) {
|
||||||
|
// ACK
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Othewise it was a NACK or Listen Window
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *response) {
|
||||||
|
|
||||||
|
if (find_listen_window(true)) {
|
||||||
|
|
||||||
|
em4x70_send_nibble(EM4X70_COMMAND_AUTH, true);
|
||||||
|
|
||||||
|
// Send 56-bit Random number
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
em4x70_send_byte(rnd[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send 7 x 0's (Diversity bits)
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
em4x70_send_bit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send 28-bit f(RN)
|
||||||
|
|
||||||
|
// Send first 24 bits
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
em4x70_send_byte(frnd[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send last 4 bits (no parity)
|
||||||
|
em4x70_send_nibble((frnd[3] >> 4) & 0xf, false);
|
||||||
|
|
||||||
|
// Receive header, 20-bit g(RN), LIW
|
||||||
|
uint8_t grnd[EM4X70_MAX_RECEIVE_LENGTH] = {0};
|
||||||
|
int num = em4x70_receive(grnd, 20);
|
||||||
|
if (num < 20) {
|
||||||
|
Dbprintf("Auth failed");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
bits2bytes(grnd, 24, response);
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_pin(const uint32_t pin) {
|
||||||
|
|
||||||
|
// sends pin code for unlocking
|
||||||
|
if (find_listen_window(true)) {
|
||||||
|
|
||||||
|
// send PIN command
|
||||||
|
em4x70_send_nibble(EM4X70_COMMAND_PIN, true);
|
||||||
|
|
||||||
|
// --> Send TAG ID (bytes 4-7)
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
em4x70_send_byte(tag.data[7 - i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --> Send PIN
|
||||||
|
for (int i = 0; i < 4 ; i++) {
|
||||||
|
em4x70_send_byte((pin >> (i * 8)) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait TWALB (write access lock bits)
|
||||||
|
WaitTicks(EM4X70_T_TAG_TWALB);
|
||||||
|
|
||||||
|
// <-- Receive ACK
|
||||||
|
if (check_ack()) {
|
||||||
|
|
||||||
|
// <w> Writes Lock Bits
|
||||||
|
WaitTicks(EM4X70_T_TAG_WEE);
|
||||||
|
// <-- Receive header + ID
|
||||||
|
uint8_t tag_id[EM4X70_MAX_RECEIVE_LENGTH];
|
||||||
|
int num = em4x70_receive(tag_id, 32);
|
||||||
|
if (num < 32) {
|
||||||
|
Dbprintf("Invalid ID Received");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
bits2bytes(tag_id, num, &tag.data[4]);
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write(const uint16_t word, const uint8_t address) {
|
||||||
|
|
||||||
|
// writes <word> to specified <address>
|
||||||
|
if (find_listen_window(true)) {
|
||||||
|
|
||||||
|
// send write command
|
||||||
|
em4x70_send_nibble(EM4X70_COMMAND_WRITE, true);
|
||||||
|
|
||||||
|
// send address data with parity bit
|
||||||
|
em4x70_send_nibble(address, true);
|
||||||
|
|
||||||
|
// send data word
|
||||||
|
em4x70_send_word(word);
|
||||||
|
|
||||||
|
// Wait TWA
|
||||||
|
WaitTicks(EM4X70_T_TAG_TWA);
|
||||||
|
|
||||||
|
// look for ACK sequence
|
||||||
|
if (check_ack()) {
|
||||||
|
|
||||||
|
// now EM4x70 needs EM4X70_T_TAG_TWEE (EEPROM write time)
|
||||||
|
// for saving data and should return with ACK
|
||||||
|
WaitTicks(EM4X70_T_TAG_WEE);
|
||||||
|
if (check_ack()) {
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool find_listen_window(bool command) {
|
static bool find_listen_window(bool command) {
|
||||||
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
while(cnt < EM4X70_T_WAITING_FOR_SNGLLIW) {
|
while (cnt < EM4X70_T_WAITING_FOR_LIW) {
|
||||||
/*
|
/*
|
||||||
80 ( 64 + 16 )
|
80 ( 64 + 16 )
|
||||||
80 ( 64 + 16 )
|
80 ( 64 + 16 )
|
||||||
|
@ -311,49 +426,46 @@ static bool find_listen_window(bool command) {
|
||||||
96 ( 64 + 32 )
|
96 ( 64 + 32 )
|
||||||
64 ( 32 + 16 +16 )*/
|
64 ( 32 + 16 +16 )*/
|
||||||
|
|
||||||
if (check_pulse_length(get_pulse_invert_length(), 80, EM4X70_TAG_TOLERANCE)) {
|
if (check_pulse_length(get_pulse_length(RISING_EDGE), (2 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_HALF_PERIOD) &&
|
||||||
if (check_pulse_length(get_pulse_invert_length(), 80, EM4X70_TAG_TOLERANCE)) {
|
check_pulse_length(get_pulse_length(RISING_EDGE), (2 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_HALF_PERIOD) &&
|
||||||
if (check_pulse_length(get_pulse_length(), 96, EM4X70_TAG_TOLERANCE)) {
|
check_pulse_length(get_pulse_length(FALLING_EDGE), (2 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_FULL_PERIOD) &&
|
||||||
if (check_pulse_length(get_pulse_length(), 64, EM4X70_TAG_TOLERANCE)) {
|
check_pulse_length(get_pulse_length(FALLING_EDGE), EM4X70_T_TAG_FULL_PERIOD + (2 * EM4X70_T_TAG_HALF_PERIOD))) {
|
||||||
if(command) {
|
|
||||||
|
if (command) {
|
||||||
/* Here we are after the 64 duration edge.
|
/* Here we are after the 64 duration edge.
|
||||||
* em4170 says we need to wait about 48 RF clock cycles.
|
* em4170 says we need to wait about 48 RF clock cycles.
|
||||||
* depends on the delay between tag and us
|
* depends on the delay between tag and us
|
||||||
*
|
*
|
||||||
* I've found between 4-5 quarter periods (32-40) works best
|
* I've found between 4-5 quarter periods (32-40) works best
|
||||||
*/
|
*/
|
||||||
WaitTicks(TICKS_PER_FC * 5 * EM4X70_T_TAG_QUARTER_PERIOD);
|
WaitTicks(4 * EM4X70_T_TAG_QUARTER_PERIOD);
|
||||||
// Send RM Command
|
// Send RM Command
|
||||||
em4x70_send_bit(0);
|
em4x70_send_bit(0);
|
||||||
em4x70_send_bit(0);
|
em4x70_send_bit(0);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bits2bytes(uint8_t *bits, int length, uint8_t *out) {
|
static void bits2bytes(const uint8_t *bits, int length, uint8_t *out) {
|
||||||
|
|
||||||
if(length%8 != 0) {
|
if (length % 8 != 0) {
|
||||||
Dbprintf("Should have a multiple of 8 bits, was sent %d", length);
|
Dbprintf("Should have a multiple of 8 bits, was sent %d", length);
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_bytes = length / 8; // We should have a multiple of 8 here
|
int num_bytes = length / 8; // We should have a multiple of 8 here
|
||||||
|
|
||||||
for(int i=1; i <= num_bytes; i++) {
|
for (int i = 1; i <= num_bytes; i++) {
|
||||||
out[num_bytes-i] = bits2byte(bits, 8);
|
out[num_bytes - i] = bits2byte(bits, 8);
|
||||||
bits+=8;
|
bits += 8;
|
||||||
//Dbprintf("Read: %02X", out[num_bytes-i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t bits2byte(uint8_t *bits, int length) {
|
static uint8_t bits2byte(const uint8_t *bits, int length) {
|
||||||
|
|
||||||
// converts <length> separate bits into a single "byte"
|
// converts <length> separate bits into a single "byte"
|
||||||
uint8_t byte = 0;
|
uint8_t byte = 0;
|
||||||
|
@ -368,22 +480,28 @@ static uint8_t bits2byte(uint8_t *bits, int length) {
|
||||||
return byte;
|
return byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static void print_array(uint8_t *bits, int len) {
|
static bool send_command_and_read(uint8_t command, uint8_t *bytes, size_t length) {
|
||||||
|
|
||||||
if(len%8 != 0) {
|
int retries = EM4X70_COMMAND_RETRIES;
|
||||||
Dbprintf("Should have a multiple of 8 bits, was sent %d", len);
|
while (retries) {
|
||||||
|
retries--;
|
||||||
|
|
||||||
|
if (find_listen_window(true)) {
|
||||||
|
uint8_t bits[EM4X70_MAX_RECEIVE_LENGTH] = {0};
|
||||||
|
size_t out_length_bits = length * 8;
|
||||||
|
em4x70_send_nibble(command, command_parity);
|
||||||
|
int len = em4x70_receive(bits, out_length_bits);
|
||||||
|
if (len < out_length_bits) {
|
||||||
|
Dbprintf("Invalid data received length: %d, expected %d", len, out_length_bits);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
bits2bytes(bits, len, bytes);
|
||||||
int num_bytes = len / 8; // We should have a multiple of 8 here
|
return true;
|
||||||
|
|
||||||
uint8_t bytes[8];
|
|
||||||
|
|
||||||
for(int i=0;i<num_bytes;i++) {
|
|
||||||
bytes[i] = bits2byte(bits, 8);
|
|
||||||
bits+=8;
|
|
||||||
Dbprintf("Read: %02X", bytes[i]);
|
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -393,18 +511,8 @@ static uint8_t bits2byte(uint8_t *bits, int length) {
|
||||||
*/
|
*/
|
||||||
static bool em4x70_read_id(void) {
|
static bool em4x70_read_id(void) {
|
||||||
|
|
||||||
if(find_listen_window(true)) {
|
return send_command_and_read(EM4X70_COMMAND_ID, &tag.data[4], 4);
|
||||||
uint8_t bits[64] = {0};
|
|
||||||
em4170_send_command(EM4X70_COMMAND_ID);
|
|
||||||
int num = em4x70_receive(bits);
|
|
||||||
if(num < 32) {
|
|
||||||
Dbprintf("Invalid ID Received");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bits2bytes(bits, num, &tag.data[4]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -413,18 +521,9 @@ static bool em4x70_read_id(void) {
|
||||||
* read user memory 1 (4 bytes including lock bits)
|
* read user memory 1 (4 bytes including lock bits)
|
||||||
*/
|
*/
|
||||||
static bool em4x70_read_um1(void) {
|
static bool em4x70_read_um1(void) {
|
||||||
if(find_listen_window(true)) {
|
|
||||||
uint8_t bits[64] = {0};
|
return send_command_and_read(EM4X70_COMMAND_UM1, &tag.data[0], 4);
|
||||||
em4170_send_command(EM4X70_COMMAND_UM1);
|
|
||||||
int num = em4x70_receive(bits);
|
|
||||||
if(num < 32) {
|
|
||||||
Dbprintf("Invalid UM1 data received");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bits2bytes(bits, num, &tag.data[0]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -434,34 +533,22 @@ static bool em4x70_read_um1(void) {
|
||||||
* read user memory 2 (8 bytes)
|
* read user memory 2 (8 bytes)
|
||||||
*/
|
*/
|
||||||
static bool em4x70_read_um2(void) {
|
static bool em4x70_read_um2(void) {
|
||||||
if(find_listen_window(true)) {
|
|
||||||
uint8_t bits[64] = {0};
|
return send_command_and_read(EM4X70_COMMAND_UM2, &tag.data[24], 8);
|
||||||
em4170_send_command(EM4X70_COMMAND_UM2);
|
|
||||||
int num = em4x70_receive(bits);
|
|
||||||
if(num < 64) {
|
|
||||||
Dbprintf("Invalid UM2 data received");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bits2bytes(bits, num, &tag.data[24]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool find_EM4X70_Tag(void) {
|
static bool find_em4x70_tag(void) {
|
||||||
Dbprintf("%s: Start", __func__);
|
|
||||||
// function is used to check wether a tag on the proxmark is an
|
// function is used to check wether a tag on the proxmark is an
|
||||||
// EM4170 tag or not -> speed up "lf search" process
|
// EM4170 tag or not -> speed up "lf search" process
|
||||||
return find_listen_window(false);
|
return find_listen_window(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int em4x70_receive(uint8_t *bits) {
|
static int em4x70_receive(uint8_t *bits, size_t length) {
|
||||||
|
|
||||||
uint32_t pl;
|
uint32_t pl;
|
||||||
int bit_pos = 0;
|
int bit_pos = 0;
|
||||||
uint8_t edge = 0;
|
edge_detection_t edge = RISING_EDGE;
|
||||||
|
|
||||||
|
|
||||||
bool foundheader = false;
|
bool foundheader = false;
|
||||||
|
|
||||||
// Read out the header
|
// Read out the header
|
||||||
|
@ -469,60 +556,58 @@ static int em4x70_receive(uint8_t *bits) {
|
||||||
// 4 Manchester 0's
|
// 4 Manchester 0's
|
||||||
|
|
||||||
// Skip a few leading 1's as it could be noisy
|
// Skip a few leading 1's as it could be noisy
|
||||||
WaitTicks(TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
WaitTicks(6 * EM4X70_T_TAG_FULL_PERIOD);
|
||||||
|
|
||||||
// wait until we get the transition from 1's to 0's which is 1.5 full windows
|
// wait until we get the transition from 1's to 0's which is 1.5 full windows
|
||||||
int pulse_count = 0;
|
for (int i = 0; i < EM4X70_T_READ_HEADER_LEN; i++) {
|
||||||
while(pulse_count < 12){
|
pl = get_pulse_length(edge);
|
||||||
pl = get_pulse_invert_length();
|
if (check_pulse_length(pl, 3 * EM4X70_T_TAG_HALF_PERIOD)) {
|
||||||
pulse_count++;
|
|
||||||
if(check_pulse_length(pl, 3 * EM4X70_T_TAG_HALF_PERIOD, EM4X70_TAG_TOLERANCE)) {
|
|
||||||
foundheader = true;
|
foundheader = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!foundheader) {
|
if (!foundheader) {
|
||||||
Dbprintf("Failed to find read header");
|
Dbprintf("Failed to find read header");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip next 3 0's, header check consumes the first 0
|
// Skip next 3 0's, header check consumes the first 0
|
||||||
for(int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
get_pulse_invert_length();
|
// If pulse length is not 1 bit, then abort early
|
||||||
|
if (!check_pulse_length(get_pulse_length(edge), EM4X70_T_TAG_FULL_PERIOD)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// identify remaining bits based on pulse lengths
|
// identify remaining bits based on pulse lengths
|
||||||
// between two listen windows only pulse lengths of 1, 1.5 and 2 are possible
|
// between listen windows only pulse lengths of 1, 1.5 and 2 are possible
|
||||||
while (true) {
|
while (bit_pos < length) {
|
||||||
|
|
||||||
if(edge)
|
pl = get_pulse_length(edge);
|
||||||
pl = get_pulse_length();
|
|
||||||
else
|
|
||||||
pl = get_pulse_invert_length();
|
|
||||||
|
|
||||||
if (check_pulse_length(pl, EM4X70_T_TAG_FULL_PERIOD, EM4X70_T_TAG_QUARTER_PERIOD)) {
|
if (check_pulse_length(pl, EM4X70_T_TAG_FULL_PERIOD)) {
|
||||||
|
|
||||||
// pulse length = 1
|
// pulse length 1 -> assign bit
|
||||||
bits[bit_pos++] = edge;
|
bits[bit_pos++] = edge == FALLING_EDGE ? 1 : 0;
|
||||||
|
|
||||||
} else if (check_pulse_length(pl, 3 * EM4X70_T_TAG_HALF_PERIOD, EM4X70_T_TAG_QUARTER_PERIOD)) {
|
} else if (check_pulse_length(pl, 3 * EM4X70_T_TAG_HALF_PERIOD)) {
|
||||||
|
|
||||||
// pulse length = 1.5 -> flip edge detection
|
// pulse length 1.5 -> 2 bits + flip edge detection
|
||||||
if(edge) {
|
if (edge == FALLING_EDGE) {
|
||||||
bits[bit_pos++] = 0;
|
bits[bit_pos++] = 0;
|
||||||
bits[bit_pos++] = 0;
|
bits[bit_pos++] = 0;
|
||||||
edge = 0;
|
edge = RISING_EDGE;
|
||||||
} else {
|
} else {
|
||||||
bits[bit_pos++] = 1;
|
bits[bit_pos++] = 1;
|
||||||
bits[bit_pos++] = 1;
|
bits[bit_pos++] = 1;
|
||||||
edge = 1;
|
edge = FALLING_EDGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (check_pulse_length(pl, 2 * EM4X70_T_TAG_FULL_PERIOD, EM4X70_T_TAG_QUARTER_PERIOD)) {
|
} else if (check_pulse_length(pl, 2 * EM4X70_T_TAG_FULL_PERIOD)) {
|
||||||
|
|
||||||
// pulse length of 2
|
// pulse length of 2 -> two bits
|
||||||
if(edge) {
|
if (edge == FALLING_EDGE) {
|
||||||
bits[bit_pos++] = 0;
|
bits[bit_pos++] = 0;
|
||||||
bits[bit_pos++] = 1;
|
bits[bit_pos++] = 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -530,15 +615,13 @@ static int em4x70_receive(uint8_t *bits) {
|
||||||
bits[bit_pos++] = 0;
|
bits[bit_pos++] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ( (edge && check_pulse_length(pl, 3 * EM4X70_T_TAG_FULL_PERIOD, EM4X70_T_TAG_QUARTER_PERIOD)) ||
|
} else {
|
||||||
(!edge && check_pulse_length(pl, 80, EM4X70_T_TAG_QUARTER_PERIOD))) {
|
// Listen Window, or invalid bit
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LIW detected (either invert or normal)
|
|
||||||
return --bit_pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bit_pos;
|
return bit_pos;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void em4x70_info(em4x70_data_t *etd) {
|
void em4x70_info(em4x70_data_t *etd) {
|
||||||
|
@ -549,10 +632,10 @@ void em4x70_info(em4x70_data_t *etd) {
|
||||||
command_parity = etd->parity;
|
command_parity = etd->parity;
|
||||||
|
|
||||||
init_tag();
|
init_tag();
|
||||||
EM4170_setup_read();
|
em4x70_setup_read();
|
||||||
|
|
||||||
// Find the Tag
|
// Find the Tag
|
||||||
if (get_signalproperties() && find_EM4X70_Tag()) {
|
if (get_signalproperties() && find_em4x70_tag()) {
|
||||||
// Read ID, UM1 and UM2
|
// Read ID, UM1 and UM2
|
||||||
status = em4x70_read_id() && em4x70_read_um1() && em4x70_read_um2();
|
status = em4x70_read_id() && em4x70_read_um1() && em4x70_read_um2();
|
||||||
}
|
}
|
||||||
|
@ -561,3 +644,166 @@ void em4x70_info(em4x70_data_t *etd) {
|
||||||
lf_finalize();
|
lf_finalize();
|
||||||
reply_ng(CMD_LF_EM4X70_INFO, status, tag.data, sizeof(tag.data));
|
reply_ng(CMD_LF_EM4X70_INFO, status, tag.data, sizeof(tag.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void em4x70_write(em4x70_data_t *etd) {
|
||||||
|
|
||||||
|
uint8_t status = 0;
|
||||||
|
|
||||||
|
command_parity = etd->parity;
|
||||||
|
|
||||||
|
init_tag();
|
||||||
|
em4x70_setup_read();
|
||||||
|
|
||||||
|
// Find the Tag
|
||||||
|
if (get_signalproperties() && find_em4x70_tag()) {
|
||||||
|
|
||||||
|
// Write
|
||||||
|
status = write(etd->word, etd->address) == PM3_SUCCESS;
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
// Read Tag after writing
|
||||||
|
if (em4x70_read_id()) {
|
||||||
|
em4x70_read_um1();
|
||||||
|
em4x70_read_um2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
StopTicks();
|
||||||
|
lf_finalize();
|
||||||
|
reply_ng(CMD_LF_EM4X70_WRITE, status, tag.data, sizeof(tag.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void em4x70_unlock(em4x70_data_t *etd) {
|
||||||
|
|
||||||
|
uint8_t status = 0;
|
||||||
|
|
||||||
|
command_parity = etd->parity;
|
||||||
|
|
||||||
|
init_tag();
|
||||||
|
em4x70_setup_read();
|
||||||
|
|
||||||
|
// Find the Tag
|
||||||
|
if (get_signalproperties() && find_em4x70_tag()) {
|
||||||
|
|
||||||
|
// Read ID (required for send_pin command)
|
||||||
|
if (em4x70_read_id()) {
|
||||||
|
|
||||||
|
// Send PIN
|
||||||
|
status = send_pin(etd->pin) == PM3_SUCCESS;
|
||||||
|
|
||||||
|
// If the write succeeded, read the rest of the tag
|
||||||
|
if (status) {
|
||||||
|
// Read Tag
|
||||||
|
// ID doesn't change
|
||||||
|
em4x70_read_um1();
|
||||||
|
em4x70_read_um2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StopTicks();
|
||||||
|
lf_finalize();
|
||||||
|
reply_ng(CMD_LF_EM4X70_UNLOCK, status, tag.data, sizeof(tag.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void em4x70_auth(em4x70_data_t *etd) {
|
||||||
|
|
||||||
|
uint8_t status = 0;
|
||||||
|
uint8_t response[3] = {0};
|
||||||
|
|
||||||
|
command_parity = etd->parity;
|
||||||
|
|
||||||
|
init_tag();
|
||||||
|
em4x70_setup_read();
|
||||||
|
|
||||||
|
// Find the Tag
|
||||||
|
if (get_signalproperties() && find_em4x70_tag()) {
|
||||||
|
|
||||||
|
// Authenticate and get tag response
|
||||||
|
status = authenticate(etd->rnd, etd->frnd, response) == PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
StopTicks();
|
||||||
|
lf_finalize();
|
||||||
|
reply_ng(CMD_LF_EM4X70_AUTH, status, response, sizeof(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
void em4x70_write_pin(em4x70_data_t *etd) {
|
||||||
|
|
||||||
|
uint8_t status = 0;
|
||||||
|
|
||||||
|
command_parity = etd->parity;
|
||||||
|
|
||||||
|
init_tag();
|
||||||
|
em4x70_setup_read();
|
||||||
|
|
||||||
|
// Find the Tag
|
||||||
|
if (get_signalproperties() && find_em4x70_tag()) {
|
||||||
|
|
||||||
|
// Read ID (required for send_pin command)
|
||||||
|
if (em4x70_read_id()) {
|
||||||
|
|
||||||
|
// Write new PIN
|
||||||
|
if ((write(etd->pin & 0xFFFF, EM4X70_PIN_WORD_UPPER) == PM3_SUCCESS) &&
|
||||||
|
(write((etd->pin >> 16) & 0xFFFF, EM4X70_PIN_WORD_LOWER) == PM3_SUCCESS)) {
|
||||||
|
|
||||||
|
// Now Try to authenticate using the new PIN
|
||||||
|
|
||||||
|
// Send PIN
|
||||||
|
status = send_pin(etd->pin) == PM3_SUCCESS;
|
||||||
|
|
||||||
|
// If the write succeeded, read the rest of the tag
|
||||||
|
if (status) {
|
||||||
|
// Read Tag
|
||||||
|
// ID doesn't change
|
||||||
|
em4x70_read_um1();
|
||||||
|
em4x70_read_um2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StopTicks();
|
||||||
|
lf_finalize();
|
||||||
|
reply_ng(CMD_LF_EM4X70_WRITEPIN, status, tag.data, sizeof(tag.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void em4x70_write_key(em4x70_data_t *etd) {
|
||||||
|
|
||||||
|
uint8_t status = 0;
|
||||||
|
|
||||||
|
command_parity = etd->parity;
|
||||||
|
|
||||||
|
init_tag();
|
||||||
|
em4x70_setup_read();
|
||||||
|
|
||||||
|
// Find the Tag
|
||||||
|
if (get_signalproperties() && find_em4x70_tag()) {
|
||||||
|
|
||||||
|
// Read ID to ensure we can write to card
|
||||||
|
if (em4x70_read_id()) {
|
||||||
|
status = 1;
|
||||||
|
|
||||||
|
// Write each crypto block
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
|
||||||
|
uint16_t key_word = (etd->crypt_key[(i * 2) + 1] << 8) + etd->crypt_key[i * 2];
|
||||||
|
// Write each word, abort if any failure occurs
|
||||||
|
if (write(key_word, 9 - i) != PM3_SUCCESS) {
|
||||||
|
status = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Ideally here we would perform a test authentication
|
||||||
|
// to ensure the new key was written correctly. This is
|
||||||
|
// what the datasheet suggests. We can't do that until
|
||||||
|
// we have the crypto algorithm implemented.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StopTicks();
|
||||||
|
lf_finalize();
|
||||||
|
reply_ng(CMD_LF_EM4X70_WRITEKEY, status, tag.data, sizeof(tag.data));
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,16 @@ typedef struct {
|
||||||
uint8_t data[32];
|
uint8_t data[32];
|
||||||
} em4x70_tag_t;
|
} em4x70_tag_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RISING_EDGE,
|
||||||
|
FALLING_EDGE
|
||||||
|
} edge_detection_t;
|
||||||
|
|
||||||
void em4x70_info(em4x70_data_t *etd);
|
void em4x70_info(em4x70_data_t *etd);
|
||||||
|
void em4x70_write(em4x70_data_t *etd);
|
||||||
|
void em4x70_unlock(em4x70_data_t *etd);
|
||||||
|
void em4x70_auth(em4x70_data_t *etd);
|
||||||
|
void em4x70_write_pin(em4x70_data_t *etd);
|
||||||
|
void em4x70_write_key(em4x70_data_t *etd);
|
||||||
|
|
||||||
#endif /* EM4x70_H */
|
#endif /* EM4x70_H */
|
||||||
|
|
|
@ -408,9 +408,9 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
// Tag CSN
|
// Tag CSN
|
||||||
|
|
||||||
uint8_t *modulated_response = NULL;
|
uint8_t *modulated_response = NULL;
|
||||||
int modulated_response_size = 0;
|
int modulated_response_size;
|
||||||
uint8_t *trace_data = NULL;
|
uint8_t *trace_data = NULL;
|
||||||
int trace_data_size = 0;
|
int trace_data_size;
|
||||||
|
|
||||||
// Respond SOF -- takes 1 bytes
|
// Respond SOF -- takes 1 bytes
|
||||||
uint8_t *resp_sof = BigBuf_malloc(1);
|
uint8_t *resp_sof = BigBuf_malloc(1);
|
||||||
|
@ -498,10 +498,9 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
|
|
||||||
bool button_pressed = false;
|
bool button_pressed = false;
|
||||||
uint8_t cmd, options, block;
|
uint8_t cmd, options, block;
|
||||||
int len = 0;
|
int len, kc_attempt = 0;
|
||||||
bool exit_loop = false;
|
bool exit_loop = false;
|
||||||
bool using_kc = false;
|
bool using_kc = false;
|
||||||
int kc_attempt = 0;
|
|
||||||
|
|
||||||
while (exit_loop == false) {
|
while (exit_loop == false) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
@ -1364,6 +1363,8 @@ static bool select_iclass_tag_ex(picopass_hdr *hdr, bool use_credit_key, uint32_
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
memcpy(hdr->epurse, resp, sizeof(hdr->epurse));
|
memcpy(hdr->epurse, resp, sizeof(hdr->epurse));
|
||||||
|
|
||||||
|
if (status)
|
||||||
*status |= FLAG_ICLASS_CC;
|
*status |= FLAG_ICLASS_CC;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -1469,16 +1470,9 @@ void ReaderIClass(uint8_t flags) {
|
||||||
switch_off();
|
switch_off();
|
||||||
}
|
}
|
||||||
|
|
||||||
// used with function select_and_auth (cmdhficlass.c)
|
|
||||||
// which needs to authenticate before doing more things like read/write
|
|
||||||
// selects and authenticate to a card, sends back div_key and mac to client.
|
|
||||||
void iClass_Authentication(uint8_t *msg) {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out) {
|
bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out) {
|
||||||
|
|
||||||
uint8_t cmd_check[9] = { ICLASS_CMD_CHECK };
|
uint8_t cmd_check[9] = { ICLASS_CMD_CHECK };
|
||||||
uint8_t div_key[8] = {0};
|
|
||||||
uint8_t mac[4] = {0};
|
uint8_t mac[4] = {0};
|
||||||
uint8_t resp_auth[4] = {0};
|
uint8_t resp_auth[4] = {0};
|
||||||
uint8_t ccnr[12] = {0};
|
uint8_t ccnr[12] = {0};
|
||||||
|
@ -1495,6 +1489,8 @@ bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint
|
||||||
memcpy(cmd_check + 1, payload->key, 8);
|
memcpy(cmd_check + 1, payload->key, 8);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
uint8_t div_key[8] = {0};
|
||||||
if (payload->use_raw)
|
if (payload->use_raw)
|
||||||
memcpy(div_key, payload->key, 8);
|
memcpy(div_key, payload->key, 8);
|
||||||
else
|
else
|
||||||
|
@ -1792,7 +1788,7 @@ static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac,
|
||||||
|
|
||||||
uint8_t resp[10] = {0};
|
uint8_t resp[10] = {0};
|
||||||
uint32_t eof_time = 0, start_time = 0;
|
uint32_t eof_time = 0, start_time = 0;
|
||||||
bool isOK = iclass_send_cmd_with_retries(write, sizeof(write), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_UPDATE, &eof_time);
|
bool isOK = iclass_send_cmd_with_retries(write, write_len, resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_UPDATE, &eof_time);
|
||||||
if (isOK == false) {
|
if (isOK == false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1833,7 +1829,7 @@ void iClass_WriteBlock(uint8_t *msg) {
|
||||||
// select tag.
|
// select tag.
|
||||||
uint32_t eof_time = 0;
|
uint32_t eof_time = 0;
|
||||||
picopass_hdr hdr = {0};
|
picopass_hdr hdr = {0};
|
||||||
bool res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time);
|
uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time);
|
||||||
if (res == false) {
|
if (res == false) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include "pm3_cmd.h"
|
#include "pm3_cmd.h"
|
||||||
|
|
||||||
void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string);
|
void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string);
|
||||||
void ReaderIClass(uint8_t arg0);
|
void ReaderIClass(uint8_t flags);
|
||||||
|
|
||||||
void iClass_WriteBlock(uint8_t *msg);
|
void iClass_WriteBlock(uint8_t *msg);
|
||||||
void iClass_Dump(uint8_t *msg);
|
void iClass_Dump(uint8_t *msg);
|
||||||
|
@ -29,7 +29,6 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
|
||||||
void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, uint8_t *datain, uint8_t *dataout, uint16_t *dataoutlen);
|
void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, uint8_t *datain, uint8_t *dataout, uint16_t *dataoutlen);
|
||||||
|
|
||||||
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
|
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
|
||||||
void iClass_Authentication(uint8_t *bytes);
|
|
||||||
bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out);
|
bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out);
|
||||||
|
|
||||||
void iClass_ReadBlock(uint8_t *msg);
|
void iClass_ReadBlock(uint8_t *msg);
|
||||||
|
|
|
@ -133,35 +133,30 @@ static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ;
|
||||||
|
|
||||||
void printHf14aConfig(void) {
|
void printHf14aConfig(void) {
|
||||||
DbpString(_CYAN_("HF 14a config"));
|
DbpString(_CYAN_("HF 14a config"));
|
||||||
Dbprintf(" [a] Anticol override....%i %s%s%s",
|
Dbprintf(" [a] Anticol override....%s%s%s",
|
||||||
hf14aconfig.forceanticol,
|
(hf14aconfig.forceanticol == 0) ? _GREEN_("std") " : follow standard " : "",
|
||||||
(hf14aconfig.forceanticol == 0) ? "( " _GREEN_("No") " ) follow standard " : "",
|
(hf14aconfig.forceanticol == 1) ? _RED_("force") " : always do anticol" : "",
|
||||||
(hf14aconfig.forceanticol == 1) ? "( " _RED_("Yes") " ) always do anticol" : "",
|
(hf14aconfig.forceanticol == 2) ? _RED_("skip") " : always skip anticol" : ""
|
||||||
(hf14aconfig.forceanticol == 2) ? "( " _RED_("Yes") " ) always skip anticol" : ""
|
|
||||||
);
|
);
|
||||||
Dbprintf(" [b] BCC override........%i %s%s%s",
|
Dbprintf(" [b] BCC override........%s%s%s",
|
||||||
hf14aconfig.forcebcc,
|
(hf14aconfig.forcebcc == 0) ? _GREEN_("std") " : follow standard" : "",
|
||||||
(hf14aconfig.forcebcc == 0) ? "( " _GREEN_("No") " ) follow standard" : "",
|
(hf14aconfig.forcebcc == 1) ? _RED_("fix") " : fix bad BCC" : "",
|
||||||
(hf14aconfig.forcebcc == 1) ? "( " _RED_("Yes") " ) always do CL2" : "",
|
(hf14aconfig.forcebcc == 2) ? _RED_("ignore") " : ignore bad BCC, always use card BCC" : ""
|
||||||
(hf14aconfig.forcebcc == 2) ? "( " _RED_("Yes") " ) always use card BCC" : ""
|
|
||||||
);
|
);
|
||||||
Dbprintf(" [2] CL2 override........%i %s%s%s",
|
Dbprintf(" [2] CL2 override........%s%s%s",
|
||||||
hf14aconfig.forcecl2,
|
(hf14aconfig.forcecl2 == 0) ? _GREEN_("std") " : follow standard" : "",
|
||||||
(hf14aconfig.forcecl2 == 0) ? "( " _GREEN_("No") " ) follow standard" : "",
|
(hf14aconfig.forcecl2 == 1) ? _RED_("force") " : always do CL2" : "",
|
||||||
(hf14aconfig.forcecl2 == 1) ? "( " _RED_("Yes") " ) always do CL2" : "",
|
(hf14aconfig.forcecl2 == 2) ? _RED_("skip") " : always skip CL2" : ""
|
||||||
(hf14aconfig.forcecl2 == 2) ? "( " _RED_("Yes") " ) always skip CL2" : ""
|
|
||||||
);
|
);
|
||||||
Dbprintf(" [3] CL3 override........%i %s%s%s",
|
Dbprintf(" [3] CL3 override........%s%s%s",
|
||||||
hf14aconfig.forcecl3,
|
(hf14aconfig.forcecl3 == 0) ? _GREEN_("std") " : follow standard" : "",
|
||||||
(hf14aconfig.forcecl3 == 0) ? "( " _GREEN_("No") " ) follow standard" : "",
|
(hf14aconfig.forcecl3 == 1) ? _RED_("force") " : always do CL3" : "",
|
||||||
(hf14aconfig.forcecl3 == 1) ? "( " _RED_("Yes") " ) always do CL3" : "",
|
(hf14aconfig.forcecl3 == 2) ? _RED_("skip") " : always skip CL3" : ""
|
||||||
(hf14aconfig.forcecl3 == 2) ? "( " _RED_("Yes") " ) always skip CL3" : ""
|
|
||||||
);
|
);
|
||||||
Dbprintf(" [r] RATS override.......%i %s%s%s",
|
Dbprintf(" [r] RATS override.......%s%s%s",
|
||||||
hf14aconfig.forcerats,
|
(hf14aconfig.forcerats == 0) ? _GREEN_("std") " : follow standard " : "",
|
||||||
(hf14aconfig.forcerats == 0) ? "( " _GREEN_("No") " ) follow standard " : "",
|
(hf14aconfig.forcerats == 1) ? _RED_("force") " : always do RATS" : "",
|
||||||
(hf14aconfig.forcerats == 1) ? "( " _RED_("Yes") " ) always do RATS" : "",
|
(hf14aconfig.forcerats == 2) ? _RED_("skip") " : always skip RATS" : ""
|
||||||
(hf14aconfig.forcerats == 2) ? "( " _RED_("Yes") " ) always skip RATS" : ""
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -921,18 +916,25 @@ bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) {
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
(void)b;
|
(void)b;
|
||||||
|
|
||||||
uint16_t check = 0;
|
uint8_t flip = 0;
|
||||||
|
uint16_t checker = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (check == 4000) {
|
WDT_HIT();
|
||||||
// if (BUTTON_PRESS() || data_available())
|
if (flip == 3) {
|
||||||
|
if (data_available())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
flip = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checker >= 3000) {
|
||||||
if (BUTTON_PRESS())
|
if (BUTTON_PRESS())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
check = 0;
|
flip++;
|
||||||
WDT_HIT();
|
checker = 0;
|
||||||
}
|
}
|
||||||
++check;
|
++checker;
|
||||||
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
@ -1340,7 +1342,6 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data, uint8_t
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
|
||||||
// main loop
|
// main loop
|
||||||
//for (;;) {
|
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
bool button_pushed = BUTTON_PRESS();
|
bool button_pushed = BUTTON_PRESS();
|
||||||
while (!button_pushed && !finished) {
|
while (!button_pushed && !finished) {
|
||||||
|
|
|
@ -129,7 +129,7 @@ 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);
|
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
|
||||||
|
|
||||||
void RAMFUNC SniffIso14443a(uint8_t param);
|
void RAMFUNC SniffIso14443a(uint8_t param);
|
||||||
void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data, uint8_t numReads);
|
void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data, uint8_t exitAfterNReads);
|
||||||
bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_info_t **responses, uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages);
|
bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_info_t **responses, uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages);
|
||||||
bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len);
|
bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len);
|
||||||
void iso14443a_antifuzz(uint32_t flags);
|
void iso14443a_antifuzz(uint32_t flags);
|
||||||
|
|
|
@ -1201,7 +1201,7 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
|
||||||
|
|
||||||
if (Handle14443bSamplesFromTag(ci, cq)) {
|
if (Handle14443bSamplesFromTag(ci, cq)) {
|
||||||
|
|
||||||
*eof_time = dma_start_time + (samples) - DELAY_TAG_TO_ARM; // end of EOF
|
*eof_time = GetCountSspClkDelta(dma_start_time) - (DELAY_TAG_TO_ARM * 128); // end of EOF
|
||||||
|
|
||||||
if (Demod.len > Demod.max_len) {
|
if (Demod.len > Demod.max_len) {
|
||||||
ret = -2; // overflow
|
ret = -2; // overflow
|
||||||
|
@ -1209,7 +1209,7 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (samples > timeout && Demod.state < DEMOD_PHASE_REF_TRAINING) {
|
if (((GetCountSspClkDelta(dma_start_time) >> 7) > timeout) && Demod.state < DEMOD_PHASE_REF_TRAINING) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1225,7 +1225,7 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
|
||||||
- (Demod.len * (8 + 2)) // time for byte transfers
|
- (Demod.len * (8 + 2)) // time for byte transfers
|
||||||
- (12) // time for SOF transfer
|
- (12) // time for SOF transfer
|
||||||
- (12); // time for EOF transfer
|
- (12); // time for EOF transfer
|
||||||
LogTrace(Demod.output, Demod.len, (sof_time * 4), (*eof_time * 4), NULL, false);
|
LogTrace(Demod.output, Demod.len, sof_time, *eof_time, NULL, false);
|
||||||
}
|
}
|
||||||
return Demod.len;
|
return Demod.len;
|
||||||
}
|
}
|
||||||
|
@ -1400,7 +1400,7 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void
|
||||||
CodeAndTransmit14443bAsReader(real_cmd, msg_len + 3, &start_time, &eof_time);
|
CodeAndTransmit14443bAsReader(real_cmd, msg_len + 3, &start_time, &eof_time);
|
||||||
|
|
||||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||||
int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, ISO14443B_READER_TIMEOUT, &eof_time);
|
int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, iso14b_timeout, &eof_time);
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
|
|
||||||
uint8_t *data_bytes = (uint8_t *) rxdata;
|
uint8_t *data_bytes = (uint8_t *) rxdata;
|
||||||
|
|
|
@ -1602,7 +1602,7 @@ void ReaderIso15693(uint32_t parameter) {
|
||||||
reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0);
|
reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
//start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||||
|
|
||||||
// we should do a better check than this
|
// we should do a better check than this
|
||||||
if (recvlen >= 12) {
|
if (recvlen >= 12) {
|
||||||
|
@ -1686,7 +1686,7 @@ void SimTagIso15693(uint8_t *uid) {
|
||||||
enum { NO_FIELD, IDLE, ACTIVATED, SELECTED, HALTED } chip_state = NO_FIELD;
|
enum { NO_FIELD, IDLE, ACTIVATED, SELECTED, HALTED } chip_state = NO_FIELD;
|
||||||
|
|
||||||
bool button_pressed = false;
|
bool button_pressed = false;
|
||||||
int vHf = 0; // in mV
|
int vHf; // in mV
|
||||||
|
|
||||||
bool exit_loop = false;
|
bool exit_loop = false;
|
||||||
while (exit_loop == false) {
|
while (exit_loop == false) {
|
||||||
|
@ -1719,7 +1719,6 @@ void SimTagIso15693(uint8_t *uid) {
|
||||||
int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &reader_eof_time);
|
int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &reader_eof_time);
|
||||||
if (cmd_len < 0) {
|
if (cmd_len < 0) {
|
||||||
button_pressed = true;
|
button_pressed = true;
|
||||||
exit_loop = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1845,9 +1844,8 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
||||||
|
|
||||||
int datalen = 5;
|
int datalen = 5;
|
||||||
uint32_t eof_time = 0;
|
uint32_t eof_time = 0;
|
||||||
uint32_t start_time = GetCountSspClk();
|
|
||||||
int recvlen = SendDataTag(data, datalen, true, speed, recv, sizeof(recv), 0, ISO15693_READER_TIMEOUT, &eof_time);
|
int recvlen = SendDataTag(data, datalen, true, speed, recv, sizeof(recv), 0, ISO15693_READER_TIMEOUT, &eof_time);
|
||||||
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
uint32_t start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ t55xx_configurations_t T55xx_Timing = {
|
||||||
{ 29 * 8, 17 * 8, 15 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0
|
{ 29 * 8, 17 * 8, 15 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0
|
||||||
{ 29 * 8, 17 * 8, 15 * 8, 31 * 8, 15 * 8, 47 * 8, 63 * 8 } // 1 of 4
|
{ 29 * 8, 17 * 8, 15 * 8, 31 * 8, 15 * 8, 47 * 8, 63 * 8 } // 1 of 4
|
||||||
#else
|
#else
|
||||||
// PM3OTHER or like offical repo
|
// PM3GENERIC or like official repo
|
||||||
{ 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Default Fixed
|
{ 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Default Fixed
|
||||||
{ 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Long Leading Ref.
|
{ 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Long Leading Ref.
|
||||||
{ 31 * 8, 20 * 8, 18 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0
|
{ 31 * 8, 20 * 8, 18 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0
|
||||||
|
@ -1009,7 +1009,7 @@ void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t cl
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
Dbprintf("Simulating with fcHigh: %d, fcLow: %d, clk: %d, STT: %d, n: %d", fchigh, fclow, clk, separator, n);
|
Dbprintf("FSK simulating with rf/%d, fc high %d, fc low %d, STT %d, n %d", clk, fchigh, fclow, separator, n);
|
||||||
|
|
||||||
if (ledcontrol) LED_A_ON();
|
if (ledcontrol) LED_A_ON();
|
||||||
SimulateTagLowFrequencyEx(n, 0, ledcontrol, numcycles);
|
SimulateTagLowFrequencyEx(n, 0, ledcontrol, numcycles);
|
||||||
|
@ -1122,10 +1122,10 @@ void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t c
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
Dbprintf("Simulating with clk: %d, invert: %d, encoding: %s (%d), separator: %d, n: %d"
|
Dbprintf("ASK simulating with rf/%d, invert %d, encoding %s (%d), separator %d, n %d"
|
||||||
, clk
|
, clk
|
||||||
, invert
|
, invert
|
||||||
, (encoding == 2) ? "BI" : (encoding == 1) ? "ASK" : "RAW"
|
, (encoding == 2) ? "ASK/BI" : (encoding == 1) ? "ASK/MAN" : "RAW/MAN"
|
||||||
, encoding
|
, encoding
|
||||||
, separator
|
, separator
|
||||||
, n
|
, n
|
||||||
|
@ -1176,7 +1176,7 @@ void CmdPSKsimTAG(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, u
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
Dbprintf("Simulating with Carrier: %d, clk: %d, invert: %d, n: %d", carrier, clk, invert, n);
|
Dbprintf("PSK simulating with rf/%d, fc/%d, invert %d, n %d", clk, carrier, invert, n);
|
||||||
|
|
||||||
if (ledcontrol) LED_A_ON();
|
if (ledcontrol) LED_A_ON();
|
||||||
SimulateTagLowFrequency(n, 0, ledcontrol);
|
SimulateTagLowFrequency(n, 0, ledcontrol);
|
||||||
|
@ -1220,7 +1220,7 @@ void CmdNRZsimTAG(uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size,
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
Dbprintf("Simulating with clk: %d, invert: %d, separator: %d, n: %d"
|
Dbprintf("NRZ simulating with rf/%d, invert %d, separator %d, n %d"
|
||||||
, clk
|
, clk
|
||||||
, invert
|
, invert
|
||||||
, separator
|
, separator
|
||||||
|
@ -1251,21 +1251,14 @@ int lf_hid_watch(int findone, uint32_t *high, uint32_t *low) {
|
||||||
BigBuf_Clear_keep_EM();
|
BigBuf_Clear_keep_EM();
|
||||||
|
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
uint16_t interval = 0;
|
for (;;) {
|
||||||
while (BUTTON_PRESS() == false) {
|
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
// cancel w usb command.
|
if (data_available() || BUTTON_PRESS()) {
|
||||||
if (interval == 4000) {
|
|
||||||
if (data_available()) {
|
|
||||||
res = PM3_EOPABORTED;
|
res = PM3_EOPABORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
interval = 0;
|
|
||||||
} else {
|
|
||||||
interval++;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoAcquisition_default(-1, false);
|
DoAcquisition_default(-1, false);
|
||||||
|
|
||||||
|
@ -1360,21 +1353,14 @@ int lf_awid_watch(int findone, uint32_t *high, uint32_t *low) {
|
||||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
||||||
|
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
uint16_t interval = 0;
|
for (;;) {
|
||||||
while (BUTTON_PRESS() == false) {
|
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
// cancel w usb command.
|
if (data_available() || BUTTON_PRESS()) {
|
||||||
if (interval == 4000) {
|
|
||||||
if (data_available()) {
|
|
||||||
res = PM3_EOPABORTED;
|
res = PM3_EOPABORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
interval = 0;
|
|
||||||
} else {
|
|
||||||
interval++;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoAcquisition_default(-1, false);
|
DoAcquisition_default(-1, false);
|
||||||
// FSK demodulator
|
// FSK demodulator
|
||||||
|
@ -1465,20 +1451,13 @@ int lf_em410x_watch(int findone, uint32_t *high, uint64_t *low) {
|
||||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
||||||
|
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
uint16_t interval = 0;
|
for (;;) {
|
||||||
while (BUTTON_PRESS() == false) {
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
// cancel w usb command.
|
if (data_available() || BUTTON_PRESS()) {
|
||||||
if (interval == 4000) {
|
|
||||||
if (data_available()) {
|
|
||||||
res = PM3_EOPABORTED;
|
res = PM3_EOPABORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
interval = 0;
|
|
||||||
} else {
|
|
||||||
interval++;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoAcquisition_default(-1, false);
|
DoAcquisition_default(-1, false);
|
||||||
|
|
||||||
|
@ -1541,21 +1520,14 @@ int lf_io_watch(int findone, uint32_t *high, uint32_t *low) {
|
||||||
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
LFSetupFPGAForADC(LF_DIVISOR_125, true);
|
||||||
|
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
uint16_t interval = 0;
|
for (;;) {
|
||||||
while (BUTTON_PRESS() == false) {
|
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
// cancel w usb command.
|
if (data_available() || BUTTON_PRESS()) {
|
||||||
if (interval == 4000) {
|
|
||||||
if (data_available()) {
|
|
||||||
res = PM3_EOPABORTED;
|
res = PM3_EOPABORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
interval = 0;
|
|
||||||
} else {
|
|
||||||
interval++;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoAcquisition_default(-1, false);
|
DoAcquisition_default(-1, false);
|
||||||
|
|
||||||
|
|
|
@ -73,11 +73,11 @@ void printSamples(void) {
|
||||||
void setSamplingConfig(sample_config *sc) {
|
void setSamplingConfig(sample_config *sc) {
|
||||||
|
|
||||||
// decimation (1-8) how many bits of adc sample value to save
|
// decimation (1-8) how many bits of adc sample value to save
|
||||||
if (sc->decimation > 0 && sc->decimation < 8)
|
if (sc->decimation > 0 && sc->decimation < 9)
|
||||||
config.decimation = sc->decimation;
|
config.decimation = sc->decimation;
|
||||||
|
|
||||||
// bits per sample (1-8)
|
// bits per sample (1-8)
|
||||||
if (sc->bits_per_sample > 0 && sc->bits_per_sample < 8)
|
if (sc->bits_per_sample > 0 && sc->bits_per_sample < 9)
|
||||||
config.bits_per_sample = sc->bits_per_sample;
|
config.bits_per_sample = sc->bits_per_sample;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -662,9 +662,11 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain) {
|
||||||
|
|
||||||
// Return 1 if the nonce is invalid else return 0
|
// Return 1 if the nonce is invalid else return 0
|
||||||
static int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
|
static int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
|
||||||
return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) & \
|
return (
|
||||||
(oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) & \
|
(oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) && \
|
||||||
(oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0)))) ? 1 : 0;
|
(oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) && \
|
||||||
|
(oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0)))
|
||||||
|
) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MifareAcquireNonces(uint32_t arg0, uint32_t flags) {
|
void MifareAcquireNonces(uint32_t arg0, uint32_t flags) {
|
||||||
|
@ -696,7 +698,7 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t flags) {
|
||||||
|
|
||||||
LED_C_ON();
|
LED_C_ON();
|
||||||
|
|
||||||
for (uint16_t i = 0; i <= PM3_CMD_DATA_SIZE - 4; i += 4) {
|
while (num_nonces < PM3_CMD_DATA_SIZE / 4) {
|
||||||
|
|
||||||
// Test if the action was cancelled
|
// Test if the action was cancelled
|
||||||
if (BUTTON_PRESS()) {
|
if (BUTTON_PRESS()) {
|
||||||
|
@ -746,18 +748,14 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t flags) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_nonces++;
|
|
||||||
|
|
||||||
// Save the tag nonce (nt)
|
// Save the tag nonce (nt)
|
||||||
buf[i] = answer[0];
|
memcpy(buf + num_nonces * 4, answer, 4);
|
||||||
buf[i + 1] = answer[1];
|
num_nonces++;
|
||||||
buf[i + 2] = answer[2];
|
|
||||||
buf[i + 3] = answer[3];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
reply_old(CMD_ACK, isOK, cuid, num_nonces - 1, buf, sizeof(buf));
|
reply_old(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
if (DBGLEVEL >= 3) DbpString("AcquireNonces finished");
|
if (DBGLEVEL >= 3) DbpString("AcquireNonces finished");
|
||||||
|
@ -826,7 +824,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
if (!have_uid) { // need a full select cycle to get the uid first
|
if (!have_uid) { // need a full select cycle to get the uid first
|
||||||
iso14a_card_select_t card_info;
|
iso14a_card_select_t card_info;
|
||||||
if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
|
if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireNonces: Can't select card (ALL)");
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireEncryptedNonces: Can't select card (ALL)");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (card_info.uidlen) {
|
switch (card_info.uidlen) {
|
||||||
|
@ -845,7 +843,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
have_uid = true;
|
have_uid = true;
|
||||||
} else { // no need for anticollision. We can directly select the card
|
} else { // no need for anticollision. We can directly select the card
|
||||||
if (!iso14443a_fast_select_card(uid, cascade_levels)) {
|
if (!iso14443a_fast_select_card(uid, cascade_levels)) {
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireNonces: Can't select card (UID)");
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireEncryptedNonces: Can't select card (UID)");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -855,7 +853,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
|
|
||||||
uint32_t nt1;
|
uint32_t nt1;
|
||||||
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
|
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireNonces: Auth1 error");
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireEncryptedNonces: Auth1 error");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,7 +864,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
CHK_TIMEOUT();
|
CHK_TIMEOUT();
|
||||||
|
|
||||||
if (len != 4) {
|
if (len != 4) {
|
||||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireNonces: Auth2 error len=%d", len);
|
if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireEncryptedNonces: Auth2 error len=%d", len);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1015,6 +1013,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rtr > 1)
|
||||||
davg = (davg + (rtr - 1) / 2) / (rtr - 1);
|
davg = (davg + (rtr - 1) / 2) / (rtr - 1);
|
||||||
|
|
||||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time);
|
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time);
|
||||||
|
@ -2714,8 +2713,8 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) {
|
||||||
//
|
//
|
||||||
// Tear-off attack against MFU.
|
// Tear-off attack against MFU.
|
||||||
// - Moebius et al
|
// - Moebius et al
|
||||||
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t tearoff_time, uint8_t *datain) {
|
void MifareU_Otp_Tearoff(uint8_t blno, uint32_t tearoff_time, uint8_t *datain) {
|
||||||
uint8_t blockNo = arg0;
|
uint8_t blockNo = blno;
|
||||||
uint8_t data_fullwrite[4] = {0x00};
|
uint8_t data_fullwrite[4] = {0x00};
|
||||||
uint8_t data_testwrite[4] = {0x00};
|
uint8_t data_testwrite[4] = {0x00};
|
||||||
memcpy(data_fullwrite, datain, 4);
|
memcpy(data_fullwrite, datain, 4);
|
||||||
|
|
|
@ -63,6 +63,6 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain);
|
||||||
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
||||||
|
|
||||||
// Tear-off test for MFU
|
// Tear-off test for MFU
|
||||||
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain);
|
void MifareU_Otp_Tearoff(uint8_t blno, uint32_t tearoff_time, uint8_t *datain);
|
||||||
void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time, uint8_t *datain);
|
void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time, uint8_t *datain);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -68,9 +68,12 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
|
||||||
|
|
||||||
// send X byte basic commands
|
// send X byte basic commands
|
||||||
int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
|
int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
|
||||||
|
|
||||||
uint8_t dcmd[data_size + 3];
|
uint8_t dcmd[data_size + 3];
|
||||||
dcmd[0] = cmd;
|
dcmd[0] = cmd;
|
||||||
|
if (data_size > 0)
|
||||||
memcpy(dcmd + 1, data, data_size);
|
memcpy(dcmd + 1, data, data_size);
|
||||||
|
|
||||||
AddCrc14A(dcmd, data_size + 1);
|
AddCrc14A(dcmd, data_size + 1);
|
||||||
ReaderTransmit(dcmd, sizeof(dcmd), timing);
|
ReaderTransmit(dcmd, sizeof(dcmd), timing);
|
||||||
int len = ReaderReceive(answer, answer_parity);
|
int len = ReaderReceive(answer, answer_parity);
|
||||||
|
|
|
@ -14,14 +14,16 @@
|
||||||
|
|
||||||
#include "proxmark3_arm.h"
|
#include "proxmark3_arm.h"
|
||||||
#include "appmain.h"
|
#include "appmain.h"
|
||||||
|
#ifndef WITH_NO_COMPRESSION
|
||||||
#include "lz4.h"
|
#include "lz4.h"
|
||||||
|
#endif
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
extern struct common_area common_area;
|
extern struct common_area common_area;
|
||||||
extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __bss_end__;
|
extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __bss_end__;
|
||||||
|
|
||||||
|
#ifndef WITH_NO_COMPRESSION
|
||||||
static void uncompress_data_section(void) {
|
static void uncompress_data_section(void) {
|
||||||
int avail_in;
|
int avail_in;
|
||||||
memcpy(&avail_in, &__data_src_start__, sizeof(int));
|
memcpy(&avail_in, &__data_src_start__, sizeof(int));
|
||||||
|
@ -35,6 +37,7 @@ static void uncompress_data_section(void) {
|
||||||
// save the size of the compressed data section
|
// save the size of the compressed data section
|
||||||
common_area.arg1 = avail_in;
|
common_area.arg1 = avail_in;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void __attribute__((section(".startos"))) Vector(void);
|
void __attribute__((section(".startos"))) Vector(void);
|
||||||
void Vector(void) {
|
void Vector(void) {
|
||||||
|
@ -48,12 +51,20 @@ void Vector(void) {
|
||||||
}
|
}
|
||||||
common_area.flags.osimage_present = 1;
|
common_area.flags.osimage_present = 1;
|
||||||
|
|
||||||
|
/* Set up data segment: Copy from flash to ram */
|
||||||
|
#ifdef WITH_NO_COMPRESSION
|
||||||
|
char *data_src = &__data_src_start__;
|
||||||
|
char *data_dst = &__data_start__;
|
||||||
|
char *data_end = &__data_end__;
|
||||||
|
while (data_dst < data_end) *data_dst++ = *data_src++;
|
||||||
|
#else
|
||||||
uncompress_data_section();
|
uncompress_data_section();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set up (that is: clear) BSS. */
|
/* Set up (that is: clear) BSS. */
|
||||||
char *dst = &__bss_start__;
|
char *bss_dst = &__bss_start__;
|
||||||
char *end = &__bss_end__;
|
char *bss_end = &__bss_end__;
|
||||||
while (dst < end) *dst++ = 0;
|
while (bss_dst < bss_end) *bss_dst++ = 0;
|
||||||
|
|
||||||
AppMain();
|
AppMain();
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ uint16_t usart_rxdata_available(void) {
|
||||||
|
|
||||||
uint32_t usart_read_ng(uint8_t *data, size_t len) {
|
uint32_t usart_read_ng(uint8_t *data, size_t len) {
|
||||||
if (len == 0) return 0;
|
if (len == 0) return 0;
|
||||||
uint32_t nbBytesRcv = 0;
|
uint32_t bytes_rcv = 0;
|
||||||
uint32_t try = 0;
|
uint32_t try = 0;
|
||||||
// uint32_t highest_observed_try = 0;
|
// uint32_t highest_observed_try = 0;
|
||||||
// Empirical max try observed: 3000000 / USART_BAUD_RATE
|
// Empirical max try observed: 3000000 / USART_BAUD_RATE
|
||||||
|
@ -146,7 +146,7 @@ uint32_t usart_read_ng(uint8_t *data, size_t len) {
|
||||||
}
|
}
|
||||||
len -= packetSize;
|
len -= packetSize;
|
||||||
while (packetSize--) {
|
while (packetSize--) {
|
||||||
data[nbBytesRcv++] = us_rxfifo[us_rxfifo_low++];
|
data[bytes_rcv++] = us_rxfifo[us_rxfifo_low++];
|
||||||
if (us_rxfifo_low == sizeof(us_rxfifo))
|
if (us_rxfifo_low == sizeof(us_rxfifo))
|
||||||
us_rxfifo_low = 0;
|
us_rxfifo_low = 0;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ uint32_t usart_read_ng(uint8_t *data, size_t len) {
|
||||||
}
|
}
|
||||||
// highest_observed_try = MAX(highest_observed_try, try);
|
// highest_observed_try = MAX(highest_observed_try, try);
|
||||||
// Dbprintf_usb("Dbg USART max observed try %i", highest_observed_try);
|
// Dbprintf_usb("Dbg USART max observed try %i", highest_observed_try);
|
||||||
return nbBytesRcv;
|
return bytes_rcv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// transfer from device to client
|
// transfer from device to client
|
||||||
|
|
|
@ -32,7 +32,7 @@ find_package(PkgConfig)
|
||||||
if (NOT SKIPQT EQUAL 1)
|
if (NOT SKIPQT EQUAL 1)
|
||||||
if(APPLE AND EXISTS /usr/local/opt/qt5)
|
if(APPLE AND EXISTS /usr/local/opt/qt5)
|
||||||
# Homebrew installs Qt5 (up to at least 5.11.0) in
|
# Homebrew installs Qt5 (up to at least 5.11.0) in
|
||||||
# /usr/local/qt5. Ensure that it can be found by CMake
|
# /usr/local/opt/qt5. Ensure that it can be found by CMake
|
||||||
# since it is not in the default /usr/local prefix.
|
# since it is not in the default /usr/local prefix.
|
||||||
# Add it to PATHS so that it doesn't override the
|
# Add it to PATHS so that it doesn't override the
|
||||||
# CMAKE_PREFIX_PATH environment variable.
|
# CMAKE_PREFIX_PATH environment variable.
|
||||||
|
@ -40,6 +40,16 @@ if (NOT SKIPQT EQUAL 1)
|
||||||
# e.g. find_package(Qt5Core ${QT_FIND_PACKAGE_OPTIONS})
|
# e.g. find_package(Qt5Core ${QT_FIND_PACKAGE_OPTIONS})
|
||||||
list(APPEND QT_FIND_PACKAGE_OPTIONS PATHS /usr/local/opt/qt5)
|
list(APPEND QT_FIND_PACKAGE_OPTIONS PATHS /usr/local/opt/qt5)
|
||||||
endif(APPLE AND EXISTS /usr/local/opt/qt5)
|
endif(APPLE AND EXISTS /usr/local/opt/qt5)
|
||||||
|
if(APPLE AND EXISTS /opt/homebrew/opt/qt5)
|
||||||
|
# Homebrew on Apple Silicon installs Qt5 in
|
||||||
|
# /opt/homebrew/opt/qt5. Ensure that it can be found by CMake
|
||||||
|
# since it is not in the default /usr/local prefix.
|
||||||
|
# Add it to PATHS so that it doesn't override the
|
||||||
|
# CMAKE_PREFIX_PATH environment variable.
|
||||||
|
# QT_FIND_PACKAGE_OPTIONS should be passed to find_package,
|
||||||
|
# e.g. find_package(Qt5Core ${QT_FIND_PACKAGE_OPTIONS})
|
||||||
|
list(APPEND QT_FIND_PACKAGE_OPTIONS PATHS /opt/homebrew/opt/qt5)
|
||||||
|
endif(APPLE AND EXISTS /opt/homebrew/opt/qt5)
|
||||||
set(QT_PACKAGELIST
|
set(QT_PACKAGELIST
|
||||||
Qt5Core
|
Qt5Core
|
||||||
Qt5Widgets
|
Qt5Widgets
|
||||||
|
@ -77,12 +87,12 @@ endif (EMBED_READLINE OR EMBED_BZIP2)
|
||||||
|
|
||||||
if (NOT SKIPREADLINE EQUAL 1)
|
if (NOT SKIPREADLINE EQUAL 1)
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
find_path(READLINE_INCLUDE_DIRS readline/readline.h /usr/local/opt/readline/include /opt/local/include /opt/include /usr/local/include /usr/include NO_DEFAULT_PATH)
|
find_path(READLINE_INCLUDE_DIRS readline/readline.h /usr/local/opt/readline/include /opt/local/include /opt/include /usr/local/include /usr/include /opt/homebrew/opt/readline/include NO_DEFAULT_PATH)
|
||||||
find_library(READLINE_LIBRARIES readline /usr/local/opt/readline/lib /opt/local/lib /opt/lib /usr/local/lib /usr/lib NO_DEFAULT_PATH)
|
find_library(READLINE_LIBRARIES readline /usr/local/opt/readline/lib /opt/local/lib /opt/lib /usr/local/lib /usr/lib /opt/homebrew/opt/readline/lib NO_DEFAULT_PATH)
|
||||||
endif (APPLE)
|
endif (APPLE)
|
||||||
if (EMBED_READLINE)
|
if (EMBED_READLINE)
|
||||||
ExternalProject_Add(ncurses
|
ExternalProject_Add(ncurses
|
||||||
URL http://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.0.tar.gz
|
URL http://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.1.tar.gz
|
||||||
PREFIX deps/ncurses
|
PREFIX deps/ncurses
|
||||||
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/ncurses
|
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/ncurses
|
||||||
CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --disable-database --with-fallbacks=ansi-generic,ansi-mini,color_xterm,dtterm,dumb,Eterm,Eterm-256color,Eterm-88color,eterm-color,gnome,gnome-256color,guru,hurd,iTerm.app,konsole,konsole-16color,konsole-256color,konsole-base,konsole-linux,konsole-solaris,konsole-vt100,kterm,kterm-color,linux,linux-16color,linux-basic,mac,mlterm,mlterm-256color,mrxvt,mrxvt-256color,mterm,mterm-ansi,mvterm,nsterm,nsterm-16color,nsterm-256color,pty,putty,putty-256color,putty-vt100,rxvt,rxvt-16color,rxvt-256color,rxvt-88color,rxvt-basic,rxvt-color,screen,screen-16color,screen-256color,simpleterm,st-16color,st-256color,st52,st52-color,stv52,tt,tt52,unknown,vt100,vt102,vte,vte-256color,xterm,xterm-16color,xterm-256color,xterm-88color,xterm-basic,xterm-bold,xterm-color,xterm-utf8,xterm-vt220,xterm-vt52,xterm1,xtermc,xtermm --enable-termcap --without-ada --without-debug --without-dlsym --without-gpm --without-develop --without-tests --without-cxx-binding --with-termlib
|
CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --disable-database --with-fallbacks=ansi-generic,ansi-mini,color_xterm,dtterm,dumb,Eterm,Eterm-256color,Eterm-88color,eterm-color,gnome,gnome-256color,guru,hurd,iTerm.app,konsole,konsole-16color,konsole-256color,konsole-base,konsole-linux,konsole-solaris,konsole-vt100,kterm,kterm-color,linux,linux-16color,linux-basic,mac,mlterm,mlterm-256color,mrxvt,mrxvt-256color,mterm,mterm-ansi,mvterm,nsterm,nsterm-16color,nsterm-256color,pty,putty,putty-256color,putty-vt100,rxvt,rxvt-16color,rxvt-256color,rxvt-88color,rxvt-basic,rxvt-color,screen,screen-16color,screen-256color,simpleterm,st-16color,st-256color,st52,st52-color,stv52,tt,tt52,unknown,vt100,vt102,vte,vte-256color,xterm,xterm-16color,xterm-256color,xterm-88color,xterm-basic,xterm-bold,xterm-color,xterm-utf8,xterm-vt220,xterm-vt52,xterm1,xtermc,xtermm --enable-termcap --without-ada --without-debug --without-dlsym --without-gpm --without-develop --without-tests --without-cxx-binding --with-termlib
|
||||||
|
@ -94,7 +104,7 @@ if (NOT SKIPREADLINE EQUAL 1)
|
||||||
ExternalProject_Add_StepTargets(ncurses configure build install)
|
ExternalProject_Add_StepTargets(ncurses configure build install)
|
||||||
|
|
||||||
ExternalProject_Add(readline
|
ExternalProject_Add(readline
|
||||||
URL ftp://ftp.gnu.org/gnu/readline/readline-7.0.tar.gz
|
URL ftp://ftp.gnu.org/gnu/readline/readline-8.1.tar.gz
|
||||||
PREFIX deps/readline
|
PREFIX deps/readline
|
||||||
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/readline
|
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/readline
|
||||||
CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --enable-static
|
CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --enable-static
|
||||||
|
@ -228,9 +238,11 @@ set (TARGET_SOURCES
|
||||||
${PM3_ROOT}/client/src/cmdhf15.c
|
${PM3_ROOT}/client/src/cmdhf15.c
|
||||||
${PM3_ROOT}/client/src/cmdhfcryptorf.c
|
${PM3_ROOT}/client/src/cmdhfcryptorf.c
|
||||||
${PM3_ROOT}/client/src/cmdhfepa.c
|
${PM3_ROOT}/client/src/cmdhfepa.c
|
||||||
|
${PM3_ROOT}/client/src/cmdhfemrtd.c
|
||||||
${PM3_ROOT}/client/src/cmdhffelica.c
|
${PM3_ROOT}/client/src/cmdhffelica.c
|
||||||
${PM3_ROOT}/client/src/cmdhffido.c
|
${PM3_ROOT}/client/src/cmdhffido.c
|
||||||
${PM3_ROOT}/client/src/cmdhficlass.c
|
${PM3_ROOT}/client/src/cmdhficlass.c
|
||||||
|
${PM3_ROOT}/client/src/cmdhfjooki.c
|
||||||
${PM3_ROOT}/client/src/cmdhflegic.c
|
${PM3_ROOT}/client/src/cmdhflegic.c
|
||||||
${PM3_ROOT}/client/src/cmdhflist.c
|
${PM3_ROOT}/client/src/cmdhflist.c
|
||||||
${PM3_ROOT}/client/src/cmdhflto.c
|
${PM3_ROOT}/client/src/cmdhflto.c
|
||||||
|
|
|
@ -17,8 +17,7 @@ vpath %.dic dictionaries
|
||||||
OBJDIR = obj
|
OBJDIR = obj
|
||||||
|
|
||||||
ifeq ($(platform),Darwin)
|
ifeq ($(platform),Darwin)
|
||||||
# cf brew info qt: qt not symlinked anymore
|
PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt/lib/pkgconfig
|
||||||
PKG_CONFIG_ENV := PKG_CONFIG_PATH=/usr/local/opt/qt/lib/pkgconfig
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
###################
|
###################
|
||||||
|
@ -115,21 +114,6 @@ STATICLIBS += $(HARDNESTEDLIB)
|
||||||
LDLIBS +=$(HARDNESTEDLIBLD)
|
LDLIBS +=$(HARDNESTEDLIBLD)
|
||||||
INCLUDES += $(HARDNESTEDLIBINC)
|
INCLUDES += $(HARDNESTEDLIBINC)
|
||||||
|
|
||||||
## Jansson
|
|
||||||
ifneq ($(SKIPJANSSONSYSTEM),1)
|
|
||||||
JANSSONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags jansson 2>/dev/null)
|
|
||||||
JANSSONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs jansson 2>/dev/null)
|
|
||||||
ifneq ($(JANSSONLDLIBS),)
|
|
||||||
JANSSONLIB =
|
|
||||||
JANSSONLIBLD = $(JANSSONLDLIBS)
|
|
||||||
JANSSONLIBINC = $(JANSSONINCLUDES)
|
|
||||||
JANSSON_FOUND = 1
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
STATICLIBS += $(JANSSONLIB)
|
|
||||||
LDLIBS += $(JANSSONLIBLD)
|
|
||||||
INCLUDES += $(JANSSONLIBINC)
|
|
||||||
|
|
||||||
## Lua
|
## Lua
|
||||||
ifneq ($(SKIPLUASYSTEM),1)
|
ifneq ($(SKIPLUASYSTEM),1)
|
||||||
LUAINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags lua5.2 2>/dev/null)
|
LUAINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags lua5.2 2>/dev/null)
|
||||||
|
@ -145,6 +129,22 @@ STATICLIBS += $(LUALIB)
|
||||||
LDLIBS += $(LUALIBLD)
|
LDLIBS += $(LUALIBLD)
|
||||||
INCLUDES += $(LUALIBINC)
|
INCLUDES += $(LUALIBINC)
|
||||||
|
|
||||||
|
## Jansson
|
||||||
|
# Jansson section needs to be after Lua to avoid interferences on macOS if a locally incompatible Lua was available, see PR 1155
|
||||||
|
ifneq ($(SKIPJANSSONSYSTEM),1)
|
||||||
|
JANSSONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags jansson 2>/dev/null)
|
||||||
|
JANSSONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs jansson 2>/dev/null)
|
||||||
|
ifneq ($(JANSSONLDLIBS),)
|
||||||
|
JANSSONLIB =
|
||||||
|
JANSSONLIBLD = $(JANSSONLDLIBS)
|
||||||
|
JANSSONLIBINC = $(JANSSONINCLUDES)
|
||||||
|
JANSSON_FOUND = 1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
STATICLIBS += $(JANSSONLIB)
|
||||||
|
LDLIBS += $(JANSSONLIBLD)
|
||||||
|
INCLUDES += $(JANSSONLIBINC)
|
||||||
|
|
||||||
## mbed TLS
|
## mbed TLS
|
||||||
# system library cannot be used because it is compiled by default without CMAC support
|
# system library cannot be used because it is compiled by default without CMAC support
|
||||||
STATICLIBS += $(MBEDTLSLIB)
|
STATICLIBS += $(MBEDTLSLIB)
|
||||||
|
@ -278,8 +278,8 @@ CXXINCLUDES += $(QTINCLUDES)
|
||||||
## Readline
|
## Readline
|
||||||
ifneq ($(SKIPREADLINE),1)
|
ifneq ($(SKIPREADLINE),1)
|
||||||
ifeq ($(platform),Darwin)
|
ifeq ($(platform),Darwin)
|
||||||
LDLIBS += -L/usr/local/opt/readline/lib
|
LDLIBS += -L$(BREW_PREFIX)/opt/readline/lib
|
||||||
INCLUDES += -I/usr/local/opt/readline/include
|
INCLUDES += -I$(BREW_PREFIX)/opt/readline/include
|
||||||
endif
|
endif
|
||||||
LDLIBS += -lreadline
|
LDLIBS += -lreadline
|
||||||
READLINE_FOUND = 1
|
READLINE_FOUND = 1
|
||||||
|
@ -469,10 +469,12 @@ SRCS = aiddesfire.c \
|
||||||
cmdhf15.c \
|
cmdhf15.c \
|
||||||
cmdhfcryptorf.c \
|
cmdhfcryptorf.c \
|
||||||
cmdhfepa.c \
|
cmdhfepa.c \
|
||||||
|
cmdhfemrtd.c \
|
||||||
cmdhffelica.c \
|
cmdhffelica.c \
|
||||||
cmdhffido.c \
|
cmdhffido.c \
|
||||||
cmdhficlass.c \
|
cmdhficlass.c \
|
||||||
cmdhflegic.c \
|
cmdhflegic.c \
|
||||||
|
cmdhfjooki.c \
|
||||||
cmdhflist.c \
|
cmdhflist.c \
|
||||||
cmdhflto.c \
|
cmdhflto.c \
|
||||||
cmdhfmf.c \
|
cmdhfmf.c \
|
||||||
|
|
|
@ -106,6 +106,7 @@ add_library(pm3rrg_rdv4 SHARED
|
||||||
${PM3_ROOT}/client/src/cmdhf15.c
|
${PM3_ROOT}/client/src/cmdhf15.c
|
||||||
${PM3_ROOT}/client/src/cmdhfcryptorf.c
|
${PM3_ROOT}/client/src/cmdhfcryptorf.c
|
||||||
${PM3_ROOT}/client/src/cmdhfepa.c
|
${PM3_ROOT}/client/src/cmdhfepa.c
|
||||||
|
${PM3_ROOT}/client/src/cmdhfemrtd.c
|
||||||
${PM3_ROOT}/client/src/cmdhffelica.c
|
${PM3_ROOT}/client/src/cmdhffelica.c
|
||||||
${PM3_ROOT}/client/src/cmdhffido.c
|
${PM3_ROOT}/client/src/cmdhffido.c
|
||||||
${PM3_ROOT}/client/src/cmdhficlass.c
|
${PM3_ROOT}/client/src/cmdhficlass.c
|
||||||
|
@ -126,9 +127,11 @@ add_library(pm3rrg_rdv4 SHARED
|
||||||
${PM3_ROOT}/client/src/cmdlfawid.c
|
${PM3_ROOT}/client/src/cmdlfawid.c
|
||||||
${PM3_ROOT}/client/src/cmdlfcotag.c
|
${PM3_ROOT}/client/src/cmdlfcotag.c
|
||||||
${PM3_ROOT}/client/src/cmdlfdestron.c
|
${PM3_ROOT}/client/src/cmdlfdestron.c
|
||||||
${PM3_ROOT}/client/src/cmdlfem4x.c
|
${PM3_ROOT}/client/src/cmdlfem.c
|
||||||
|
${PM3_ROOT}/client/src/cmdlfem410x.c
|
||||||
${PM3_ROOT}/client/src/cmdlfem4x05.c
|
${PM3_ROOT}/client/src/cmdlfem4x05.c
|
||||||
${PM3_ROOT}/client/src/cmdlfem4x50.c
|
${PM3_ROOT}/client/src/cmdlfem4x50.c
|
||||||
|
${PM3_ROOT}/client/src/cmdlfem4x70.c
|
||||||
${PM3_ROOT}/client/src/cmdlffdxb.c
|
${PM3_ROOT}/client/src/cmdlffdxb.c
|
||||||
${PM3_ROOT}/client/src/cmdlfgallagher.c
|
${PM3_ROOT}/client/src/cmdlfgallagher.c
|
||||||
${PM3_ROOT}/client/src/cmdlfguard.c
|
${PM3_ROOT}/client/src/cmdlfguard.c
|
||||||
|
|
|
@ -74,13 +74,13 @@ static bool OpenPm3(void) {
|
||||||
jint Console(JNIEnv *env, jobject instance, jstring cmd_) {
|
jint Console(JNIEnv *env, jobject instance, jstring cmd_) {
|
||||||
|
|
||||||
if (!conn.run) {
|
if (!conn.run) {
|
||||||
if (OpenPm3() && TestProxmark() == PM3_SUCCESS) {
|
if (OpenPm3() && TestProxmark(session.current_device) == PM3_SUCCESS) {
|
||||||
LOGD("Connected to device");
|
LOGD("Connected to device");
|
||||||
PrintAndLogEx(SUCCESS, "Connected to device");
|
PrintAndLogEx(SUCCESS, "Connected to device");
|
||||||
} else {
|
} else {
|
||||||
LOGD("Failed to connect to device");
|
LOGD("Failed to connect to device");
|
||||||
PrintAndLogEx(ERR, "Failed to connect to device");
|
PrintAndLogEx(ERR, "Failed to connect to device");
|
||||||
CloseProxmark();
|
CloseProxmark(session.current_device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,10 +110,10 @@ jboolean IsClientRunning(JNIEnv *env, jobject instance) {
|
||||||
* */
|
* */
|
||||||
jboolean TestPm3(JNIEnv *env, jobject instance) {
|
jboolean TestPm3(JNIEnv *env, jobject instance) {
|
||||||
if (open() == false) {
|
if (open() == false) {
|
||||||
CloseProxmark();
|
CloseProxmark(session.current_device);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool ret = (TestProxmark() == PM3_SUCCESS);
|
bool ret = (TestProxmark(session.current_device) == PM3_SUCCESS);
|
||||||
return (jboolean)(ret);
|
return (jboolean)(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ jboolean TestPm3(JNIEnv *env, jobject instance) {
|
||||||
* stop pm3 client
|
* stop pm3 client
|
||||||
* */
|
* */
|
||||||
void ClosePm3(JNIEnv *env, jobject instance) {
|
void ClosePm3(JNIEnv *env, jobject instance) {
|
||||||
CloseProxmark();
|
CloseProxmark(session.current_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -3,4 +3,4 @@
|
||||||
mem load -f mfc_default_keys --mfc
|
mem load -f mfc_default_keys --mfc
|
||||||
mem load -f t55xx_default_pwds --t55xx
|
mem load -f t55xx_default_pwds --t55xx
|
||||||
mem load -f iclass_default_keys --iclass
|
mem load -f iclass_default_keys --iclass
|
||||||
lf t55xx deviceconfig z p
|
lf t55xx deviceconfig -z -p
|
||||||
|
|
|
@ -14,10 +14,18 @@ add_library(pm3rrg_rdv4_amiibo STATIC
|
||||||
if (NOT TARGET pm3rrg_rdv4_mbedtls)
|
if (NOT TARGET pm3rrg_rdv4_mbedtls)
|
||||||
include(mbedtls.cmake)
|
include(mbedtls.cmake)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(pm3rrg_rdv4_amiibo PRIVATE
|
target_link_libraries(pm3rrg_rdv4_amiibo PRIVATE
|
||||||
m
|
m
|
||||||
pm3rrg_rdv4_mbedtls)
|
pm3rrg_rdv4_mbedtls)
|
||||||
target_include_directories(pm3rrg_rdv4_amiibo PRIVATE ../../include ../../common)
|
|
||||||
target_include_directories(pm3rrg_rdv4_amiibo INTERFACE amiitool)
|
|
||||||
target_compile_options(pm3rrg_rdv4_amiibo PRIVATE -Wall -Werror -O3)
|
target_compile_options(pm3rrg_rdv4_amiibo PRIVATE -Wall -Werror -O3)
|
||||||
set_property(TARGET pm3rrg_rdv4_amiibo PROPERTY POSITION_INDEPENDENT_CODE ON)
|
set_property(TARGET pm3rrg_rdv4_amiibo PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
target_include_directories(pm3rrg_rdv4_amiibo PRIVATE amiitool
|
||||||
|
../../common
|
||||||
|
../../include
|
||||||
|
../src
|
||||||
|
jansson)
|
||||||
|
|
||||||
|
target_include_directories(pm3rrg_rdv4_amiibo INTERFACE amiitool)
|
|
@ -1,5 +1,5 @@
|
||||||
MYSRCPATHS =
|
MYSRCPATHS =
|
||||||
MYINCLUDES = -I. -I.. -I../jansson -I../../../common -I../../../common/mbedtls -I../../../include
|
MYINCLUDES = -I. -I.. -I../../../common -I../../../common/mbedtls -I../../../include -I../../src -I../../../include -I../jansson
|
||||||
MYCFLAGS =
|
MYCFLAGS =
|
||||||
MYDEFS =
|
MYDEFS =
|
||||||
MYSRCS = \
|
MYSRCS = \
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "md.h"
|
#include "md.h"
|
||||||
#include "aes.h"
|
#include "aes.h"
|
||||||
#include "commonutil.h"
|
#include "commonutil.h"
|
||||||
|
#include "../src/fileutils.h"
|
||||||
|
|
||||||
#define HMAC_POS_DATA 0x008
|
#define HMAC_POS_DATA 0x008
|
||||||
#define HMAC_POS_TAG 0x1B4
|
#define HMAC_POS_TAG 0x1B4
|
||||||
|
@ -131,24 +132,29 @@ void nfc3d_amiibo_pack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *plain
|
||||||
nfc3d_amiibo_internal_to_tag(cipher, tag);
|
nfc3d_amiibo_internal_to_tag(cipher, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys, const char *path) {
|
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys) {
|
||||||
FILE *f = fopen(path, "rb");
|
|
||||||
if (!f) {
|
#define amiboo_key_fn "key_retail.bin"
|
||||||
|
|
||||||
|
uint8_t *dump = NULL;
|
||||||
|
size_t bytes_read = 0;
|
||||||
|
if (loadFile_safe(amiboo_key_fn, "", (void **)&dump, &bytes_read) != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", amiboo_key_fn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = fread(amiiboKeys, sizeof(*amiiboKeys), 1, f);
|
if (bytes_read != sizeof(*amiiboKeys)) {
|
||||||
fclose(f);
|
free(dump);
|
||||||
|
|
||||||
if (len != sizeof(*amiiboKeys)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((amiiboKeys->data.magicBytesSize > 16) ||
|
if ((amiiboKeys->data.magicBytesSize > 16) || (amiiboKeys->tag.magicBytesSize > 16)) {
|
||||||
(amiiboKeys->tag.magicBytesSize > 16)) {
|
free(dump);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(amiiboKeys, dump, bytes_read);
|
||||||
|
free(dump);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ typedef struct {
|
||||||
|
|
||||||
bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *tag, uint8_t *plain);
|
bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *tag, uint8_t *plain);
|
||||||
void nfc3d_amiibo_pack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *plain, uint8_t *tag);
|
void nfc3d_amiibo_pack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *plain, uint8_t *tag);
|
||||||
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys, const char *path);
|
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys);
|
||||||
void nfc3d_amiibo_copy_app_data(const uint8_t *src, uint8_t *dst);
|
void nfc3d_amiibo_copy_app_data(const uint8_t *src, uint8_t *dst);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,15 +33,6 @@ void amiitool_usage(void) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadAmiikey(nfc3d_amiibo_keys keys, char *keyfile) {
|
|
||||||
|
|
||||||
if (!nfc3d_amiibo_load_keys(&keys, keyfile)) {
|
|
||||||
PrintAndLogEx(ERR, "Could not load keys from '%s'", keyfile);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
self = argv[0];
|
self = argv[0];
|
||||||
|
|
||||||
|
|
|
@ -830,7 +830,7 @@ static void arg_date_errorfn(
|
||||||
/* make argval NULL safe */
|
/* make argval NULL safe */
|
||||||
argval = argval ? argval : "";
|
argval = argval ? argval : "";
|
||||||
|
|
||||||
fprintf(fp, "%s: ", progname);
|
fprintf(fp, "[!] %s: ", progname);
|
||||||
switch (errorcode) {
|
switch (errorcode) {
|
||||||
case EMINCOUNT:
|
case EMINCOUNT:
|
||||||
fputs("missing option ", fp);
|
fputs("missing option ", fp);
|
||||||
|
@ -846,11 +846,11 @@ static void arg_date_errorfn(
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
char buff[200];
|
char buff[200];
|
||||||
|
|
||||||
fprintf(fp, "illegal timestamp format \"%s\"\n", argval);
|
fprintf(fp, "[!] illegal timestamp format \"%s\"\n", argval);
|
||||||
memset(&tm, 0, sizeof(tm));
|
memset(&tm, 0, sizeof(tm));
|
||||||
arg_strptime("1999-12-31 23:59:59", "%F %H:%M:%S", &tm);
|
arg_strptime("1999-12-31 23:59:59", "%F %H:%M:%S", &tm);
|
||||||
strftime(buff, sizeof(buff), parent->format, &tm);
|
strftime(buff, sizeof(buff), parent->format, &tm);
|
||||||
printf("correct format is \"%s\"\n", buff);
|
printf("[+] correct format is \"%s\"\n", buff);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1442,7 +1442,7 @@ static void arg_dbl_errorfn(
|
||||||
/* make argval NULL safe */
|
/* make argval NULL safe */
|
||||||
argval = argval ? argval : "";
|
argval = argval ? argval : "";
|
||||||
|
|
||||||
fprintf(fp, "%s: ", progname);
|
fprintf(fp, "[!] %s: ", progname);
|
||||||
switch (errorcode) {
|
switch (errorcode) {
|
||||||
case EMINCOUNT:
|
case EMINCOUNT:
|
||||||
fputs("missing option ", fp);
|
fputs("missing option ", fp);
|
||||||
|
@ -1455,7 +1455,7 @@ static void arg_dbl_errorfn(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EBADDOUBLE:
|
case EBADDOUBLE:
|
||||||
fprintf(fp, "invalid argument \"%s\" to option ", argval);
|
fprintf(fp, "[!] invalid argument \"%s\" to option ", argval);
|
||||||
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1805,7 +1805,7 @@ static void arg_file_errorfn(
|
||||||
/* make argval NULL safe */
|
/* make argval NULL safe */
|
||||||
argval = argval ? argval : "";
|
argval = argval ? argval : "";
|
||||||
|
|
||||||
fprintf(fp, "%s: ", progname);
|
fprintf(fp, "[!] %s: ", progname);
|
||||||
switch (errorcode) {
|
switch (errorcode) {
|
||||||
case EMINCOUNT:
|
case EMINCOUNT:
|
||||||
fputs("missing option ", fp);
|
fputs("missing option ", fp);
|
||||||
|
@ -1818,7 +1818,7 @@ static void arg_file_errorfn(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(fp, "unknown error at \"%s\"\n", argval);
|
fprintf(fp, "[!] unknown error at \"%s\"\n", argval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2136,7 +2136,7 @@ static void arg_int_errorfn(
|
||||||
/* make argval NULL safe */
|
/* make argval NULL safe */
|
||||||
argval = argval ? argval : "";
|
argval = argval ? argval : "";
|
||||||
|
|
||||||
fprintf(fp, "%s: ", progname);
|
fprintf(fp, "[!] %s: ", progname);
|
||||||
switch (errorcode) {
|
switch (errorcode) {
|
||||||
case EMINCOUNT:
|
case EMINCOUNT:
|
||||||
fputs("missing option ", fp);
|
fputs("missing option ", fp);
|
||||||
|
@ -2149,7 +2149,7 @@ static void arg_int_errorfn(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EBADINT:
|
case EBADINT:
|
||||||
fprintf(fp, "invalid argument \"%s\" to option ", argval);
|
fprintf(fp, "[!] invalid argument \"%s\" to option ", argval);
|
||||||
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2394,7 +2394,7 @@ static void arg_u64_errorfn(
|
||||||
/* make argval NULL safe */
|
/* make argval NULL safe */
|
||||||
argval = argval ? argval : "";
|
argval = argval ? argval : "";
|
||||||
|
|
||||||
fprintf(fp, "%s: ", progname);
|
fprintf(fp, "[!] %s: ", progname);
|
||||||
switch (errorcode) {
|
switch (errorcode) {
|
||||||
case EMINCOUNT:
|
case EMINCOUNT:
|
||||||
fputs("missing option ", fp);
|
fputs("missing option ", fp);
|
||||||
|
@ -2407,7 +2407,7 @@ static void arg_u64_errorfn(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EBADINT:
|
case EBADINT:
|
||||||
fprintf(fp, "invalid argument \"%s\" to option ", argval);
|
fprintf(fp, "[!] invalid argument \"%s\" to option ", argval);
|
||||||
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2554,18 +2554,18 @@ static void arg_lit_errorfn(
|
||||||
|
|
||||||
switch (errorcode) {
|
switch (errorcode) {
|
||||||
case EMINCOUNT:
|
case EMINCOUNT:
|
||||||
fprintf(fp, "%s: missing option ", progname);
|
fprintf(fp, "[!] %s: missing option ", progname);
|
||||||
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EMAXCOUNT:
|
case EMAXCOUNT:
|
||||||
fprintf(fp, "%s: extraneous option ", progname);
|
fprintf(fp, "[!] %s: extraneous option ", progname);
|
||||||
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARG_TRACE(("%s:errorfn(%p, %p, %d, %s, %s)\n", __FILE__, parent, fp,
|
ARG_TRACE(("[!] %s:errorfn(%p, %p, %d, %s, %s)\n", __FILE__, parent, fp,
|
||||||
errorcode, argval, progname));
|
errorcode, argval, progname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2859,7 +2859,7 @@ static void arg_rex_errorfn(struct arg_rex *parent,
|
||||||
/* make argval NULL safe */
|
/* make argval NULL safe */
|
||||||
argval = argval ? argval : "";
|
argval = argval ? argval : "";
|
||||||
|
|
||||||
fprintf(fp, "%s: ", progname);
|
fprintf(fp, "[!] %s: ", progname);
|
||||||
switch (errorcode) {
|
switch (errorcode) {
|
||||||
case EMINCOUNT:
|
case EMINCOUNT:
|
||||||
fputs("missing option ", fp);
|
fputs("missing option ", fp);
|
||||||
|
@ -3790,7 +3790,7 @@ static void arg_str_errorfn(
|
||||||
/* make argval NULL safe */
|
/* make argval NULL safe */
|
||||||
argval = argval ? argval : "";
|
argval = argval ? argval : "";
|
||||||
|
|
||||||
fprintf(fp, "%s: ", progname);
|
fprintf(fp, "[!] %s: ", progname);
|
||||||
switch (errorcode) {
|
switch (errorcode) {
|
||||||
case EMINCOUNT:
|
case EMINCOUNT:
|
||||||
fputs("missing option ", fp);
|
fputs("missing option ", fp);
|
||||||
|
|
|
@ -118,7 +118,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
||||||
if (nerrors > 0) {
|
if (nerrors > 0) {
|
||||||
/* Display the error details contained in the arg_end struct.*/
|
/* Display the error details contained in the arg_end struct.*/
|
||||||
arg_print_errors(stdout, ((struct arg_end *)(ctx->argtable)[vargtableLen - 1]), ctx->programName);
|
arg_print_errors(stdout, ((struct arg_end *)(ctx->argtable)[vargtableLen - 1]), ctx->programName);
|
||||||
PrintAndLogEx(WARNING, "Try '%s --help' for more information.\n", ctx->programName);
|
PrintAndLogEx(WARNING, "Try " _YELLOW_("'%s --help'") " for more information.\n", ctx->programName);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
@ -269,15 +269,19 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hexstr -> u64, w optional len input and default value fallback.
|
||||||
|
// 0 = failed
|
||||||
|
// 1 = OK
|
||||||
|
// 3 = optional param - not set
|
||||||
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def) {
|
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def) {
|
||||||
uint64_t rv = 0;
|
uint64_t rv = 0;
|
||||||
uint8_t data[8];
|
uint8_t d[8];
|
||||||
int datalen = 0;
|
int dlen = 0;
|
||||||
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), data, sizeof(data), &datalen);
|
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), d, sizeof(d), &dlen);
|
||||||
if (res == 0 && datalen > 0) {
|
if (res == 0 && dlen > 0) {
|
||||||
for (uint8_t i = 0; i < datalen; i++) {
|
for (uint8_t i = 0; i < dlen; i++) {
|
||||||
rv <<= 8;
|
rv <<= 8;
|
||||||
rv |= data[i];
|
rv |= d[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rv = def;
|
rv = def;
|
||||||
|
@ -285,4 +289,56 @@ uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hexstr -> u64, w optional len input and default value fallback.
|
||||||
|
// 0 = failed
|
||||||
|
// 1 = OK
|
||||||
|
// 2 = wrong len param, use default
|
||||||
|
// 3 = optional param, if fail, use default.
|
||||||
|
int arg_get_u64_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint64_t def, uint64_t *out, uint8_t nlen, bool optional) {
|
||||||
|
int n = 0;
|
||||||
|
uint8_t d[nlen];
|
||||||
|
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), d, sizeof(d), &n);
|
||||||
|
if (res == 0 && n == nlen) {
|
||||||
|
uint64_t rv = 0;
|
||||||
|
for (uint8_t i = 0; i < n; i++) {
|
||||||
|
rv <<= 8;
|
||||||
|
rv |= d[i];
|
||||||
|
}
|
||||||
|
*out = rv;
|
||||||
|
return 1;
|
||||||
|
} else if (res == 0 && n) {
|
||||||
|
*out = def;
|
||||||
|
return 2;
|
||||||
|
} else if (res == 0 && n == 0 && optional) {
|
||||||
|
*out = def;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int arg_get_u32_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out) {
|
||||||
|
return arg_get_u32_hexstr_def_nlen(ctx, paramnum, def, out, 4, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int arg_get_u32_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out, uint8_t nlen, bool optional) {
|
||||||
|
int n = 0;
|
||||||
|
uint8_t d[nlen];
|
||||||
|
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), d, sizeof(d), &n);
|
||||||
|
if (res == 0 && n == nlen) {
|
||||||
|
uint32_t rv = 0;
|
||||||
|
for (uint8_t i = 0; i < n; i++) {
|
||||||
|
rv <<= 8;
|
||||||
|
rv |= d[i];
|
||||||
|
}
|
||||||
|
*out = rv;
|
||||||
|
return 1;
|
||||||
|
} else if (res == 0 && n) {
|
||||||
|
*out = def;
|
||||||
|
return 2;
|
||||||
|
} else if (res == 0 && n == 0 && optional) {
|
||||||
|
*out = def;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,4 +68,13 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
||||||
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
|
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
|
||||||
|
|
||||||
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def);
|
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def);
|
||||||
|
int arg_get_u64_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint64_t def, uint64_t *out, uint8_t nlen, bool optional);
|
||||||
|
int arg_get_u32_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out);
|
||||||
|
int arg_get_u32_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out, uint8_t nlen, bool optional);
|
||||||
|
|
||||||
|
#define CP_SUCCESS_OPTIONAL 1
|
||||||
|
#define CP_SUCCESS 0
|
||||||
|
#define CP_ENOPARAM -1
|
||||||
|
#define CP_WRONGLEN -2
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -143,7 +143,7 @@ bitslice_test_nonces_t bitslice_test_nonces_NOSIMD;
|
||||||
bitslice_test_nonces_t bitslice_test_nonces_dispatch;
|
bitslice_test_nonces_t bitslice_test_nonces_dispatch;
|
||||||
|
|
||||||
#if defined (_WIN32)
|
#if defined (_WIN32)
|
||||||
#define malloc_bitslice(x) __builtin_assume_aligned(_aligned_malloc((x), MAX_BITSLICES/8), MAX_BITSLICES/8)
|
#define malloc_bitslice(x) __builtin_assume_aligned(_aligned_malloc((x), MAX_BITSLICES / 8), MAX_BITSLICES / 8)
|
||||||
#define free_bitslice(x) _aligned_free(x)
|
#define free_bitslice(x) _aligned_free(x)
|
||||||
#elif defined (__APPLE__)
|
#elif defined (__APPLE__)
|
||||||
static void *malloc_bitslice(size_t x) {
|
static void *malloc_bitslice(size_t x) {
|
||||||
|
@ -156,7 +156,7 @@ static void *malloc_bitslice(size_t x) {
|
||||||
}
|
}
|
||||||
#define free_bitslice(x) free(x)
|
#define free_bitslice(x) free(x)
|
||||||
#else
|
#else
|
||||||
#define malloc_bitslice(x) memalign(MAX_BITSLICES/8, (x))
|
#define malloc_bitslice(x) memalign(MAX_BITSLICES / 8, (x))
|
||||||
#define free_bitslice(x) free(x)
|
#define free_bitslice(x) free(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -559,6 +559,10 @@ void SetSIMDInstr(SIMDExecInstr instr) {
|
||||||
static SIMDExecInstr GetSIMDInstr(void) {
|
static SIMDExecInstr GetSIMDInstr(void) {
|
||||||
SIMDExecInstr instr;
|
SIMDExecInstr instr;
|
||||||
|
|
||||||
|
#if defined(COMPILER_HAS_SIMD)
|
||||||
|
__builtin_cpu_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(COMPILER_HAS_SIMD_AVX512)
|
#if defined(COMPILER_HAS_SIMD_AVX512)
|
||||||
if (__builtin_cpu_supports("avx512f"))
|
if (__builtin_cpu_supports("avx512f"))
|
||||||
instr = SIMD_AVX512;
|
instr = SIMD_AVX512;
|
||||||
|
|
|
@ -465,7 +465,8 @@ float brute_force_benchmark(void) {
|
||||||
|
|
||||||
free(test_candidates[0].states[ODD_STATE]);
|
free(test_candidates[0].states[ODD_STATE]);
|
||||||
free(test_candidates[0].states[EVEN_STATE]);
|
free(test_candidates[0].states[EVEN_STATE]);
|
||||||
|
test_candidates[0].len[ODD_STATE] = 0;
|
||||||
|
test_candidates[0].len[EVEN_STATE] = 0;
|
||||||
return bf_rate;
|
return bf_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
typedef struct guess_sum_a8 {
|
typedef struct guess_sum_a8 {
|
||||||
float prob;
|
float prob;
|
||||||
uint64_t num_states;
|
uint64_t num_states;
|
||||||
uint8_t sum_a8_idx;
|
uint16_t sum_a8_idx;
|
||||||
} guess_sum_a8_t;
|
} guess_sum_a8_t;
|
||||||
|
|
||||||
typedef struct noncelistentry {
|
typedef struct noncelistentry {
|
||||||
|
@ -40,7 +40,7 @@ typedef struct noncelist {
|
||||||
guess_sum_a8_t sum_a8_guess[NUM_SUMS];
|
guess_sum_a8_t sum_a8_guess[NUM_SUMS];
|
||||||
bool sum_a8_guess_dirty;
|
bool sum_a8_guess_dirty;
|
||||||
float expected_num_brute_force;
|
float expected_num_brute_force;
|
||||||
uint8_t BitFlips[0x400];
|
uint16_t BitFlips[0x400];
|
||||||
uint32_t *states_bitarray[2];
|
uint32_t *states_bitarray[2];
|
||||||
uint32_t num_states_bitarray[2];
|
uint32_t num_states_bitarray[2];
|
||||||
bool all_bitflips_dirty[2];
|
bool all_bitflips_dirty[2];
|
||||||
|
|
|
@ -372,10 +372,11 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
|
||||||
for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {
|
for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {
|
||||||
count[odd_even] = count_states(test_bitarray[odd_even]);
|
count[odd_even] = count_states(test_bitarray[odd_even]);
|
||||||
if (count[odd_even] != 1 << 24) {
|
if (count[odd_even] != 1 << 24) {
|
||||||
printf("Writing %u possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n",
|
printf("Writing %u possible %s states for bitflip property %03x (%u (%1.2f%%) states eliminated)\n",
|
||||||
count[odd_even],
|
count[odd_even],
|
||||||
odd_even == EVEN_STATE ? "even" : "odd",
|
odd_even == EVEN_STATE ? "even" : "odd",
|
||||||
bitflip, (1 << 24) - count[odd_even],
|
bitflip,
|
||||||
|
(1 << 24) - count[odd_even],
|
||||||
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
||||||
#ifndef TEST_RUN
|
#ifndef TEST_RUN
|
||||||
write_bitflips_file(odd_even, bitflip, sum_a0, test_bitarray[odd_even], count[odd_even]);
|
write_bitflips_file(odd_even, bitflip, sum_a0, test_bitarray[odd_even], count[odd_even]);
|
||||||
|
@ -399,10 +400,11 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
|
||||||
}
|
}
|
||||||
count[odd_even] = count_states(test_bitarray_2nd);
|
count[odd_even] = count_states(test_bitarray_2nd);
|
||||||
if (count[odd_even] != 1 << 24) {
|
if (count[odd_even] != 1 << 24) {
|
||||||
printf("Writing %u possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n",
|
printf("Writing %u possible %s states for bitflip property %03x (%u (%1.2f%%) states eliminated)\n",
|
||||||
count[odd_even],
|
count[odd_even],
|
||||||
odd_even == EVEN_STATE ? "even" : "odd",
|
odd_even == EVEN_STATE ? "even" : "odd",
|
||||||
bitflip | BITFLIP_2ND_BYTE, (1 << 24) - count[odd_even],
|
bitflip | BITFLIP_2ND_BYTE,
|
||||||
|
(1 << 24) - count[odd_even],
|
||||||
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
||||||
#ifndef TEST_RUN
|
#ifndef TEST_RUN
|
||||||
write_bitflips_file(odd_even, bitflip | BITFLIP_2ND_BYTE, sum_a0, test_bitarray_2nd, count[odd_even]);
|
write_bitflips_file(odd_even, bitflip | BITFLIP_2ND_BYTE, sum_a0, test_bitarray_2nd, count[odd_even]);
|
||||||
|
@ -484,10 +486,11 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
|
||||||
for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {
|
for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {
|
||||||
count[odd_even] = count_states(test_not_bitarray[odd_even]);
|
count[odd_even] = count_states(test_not_bitarray[odd_even]);
|
||||||
if (count[odd_even] != 1 << 24) {
|
if (count[odd_even] != 1 << 24) {
|
||||||
printf("Writing %u possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n",
|
printf("Writing %u possible %s states for bitflip property %03x (%u (%1.2f%%) states eliminated)\n",
|
||||||
count[odd_even],
|
count[odd_even],
|
||||||
odd_even == EVEN_STATE ? "even" : "odd",
|
odd_even == EVEN_STATE ? "even" : "odd",
|
||||||
bitflip | 0x100, (1 << 24) - count[odd_even],
|
bitflip | 0x100,
|
||||||
|
(1 << 24) - count[odd_even],
|
||||||
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
||||||
#ifndef TEST_RUN
|
#ifndef TEST_RUN
|
||||||
write_bitflips_file(odd_even, bitflip | 0x100, sum_a0, test_not_bitarray[odd_even], count[odd_even]);
|
write_bitflips_file(odd_even, bitflip | 0x100, sum_a0, test_not_bitarray[odd_even], count[odd_even]);
|
||||||
|
@ -511,10 +514,11 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
|
||||||
}
|
}
|
||||||
count[odd_even] = count_states(test_bitarray_2nd);
|
count[odd_even] = count_states(test_bitarray_2nd);
|
||||||
if (count[odd_even] != 1 << 24) {
|
if (count[odd_even] != 1 << 24) {
|
||||||
printf("Writing %u possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n",
|
printf("Writing %u possible %s states for bitflip property %03x (%u (%1.2f%%) states eliminated)\n",
|
||||||
count[odd_even],
|
count[odd_even],
|
||||||
odd_even == EVEN_STATE ? "even" : "odd",
|
odd_even == EVEN_STATE ? "even" : "odd",
|
||||||
bitflip | 0x100 | BITFLIP_2ND_BYTE, (1 << 24) - count[odd_even],
|
bitflip | 0x100 | BITFLIP_2ND_BYTE,
|
||||||
|
(1 << 24) - count[odd_even],
|
||||||
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
(float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0);
|
||||||
#ifndef TEST_RUN
|
#ifndef TEST_RUN
|
||||||
write_bitflips_file(odd_even, bitflip | 0x100 | BITFLIP_2ND_BYTE, sum_a0, test_bitarray_2nd, count[odd_even]);
|
write_bitflips_file(odd_even, bitflip | 0x100 | BITFLIP_2ND_BYTE, sum_a0, test_bitarray_2nd, count[odd_even]);
|
||||||
|
@ -532,7 +536,6 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
|
||||||
free_bitarray(test_not_bitarray[EVEN_STATE]);
|
free_bitarray(test_not_bitarray[EVEN_STATE]);
|
||||||
free_bitarray(test_bitarray[ODD_STATE]);
|
free_bitarray(test_bitarray[ODD_STATE]);
|
||||||
free_bitarray(test_bitarray[EVEN_STATE]);
|
free_bitarray(test_bitarray[EVEN_STATE]);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1284,3 +1284,12 @@ AABAFFCC7612
|
||||||
#
|
#
|
||||||
534F4C415249
|
534F4C415249
|
||||||
534f4c303232
|
534f4c303232
|
||||||
|
#
|
||||||
|
# Nespresso, smart card
|
||||||
|
# key-gen algo, these keys are for one card
|
||||||
|
ff9a84635bd2
|
||||||
|
6f30126ee7e4
|
||||||
|
6039abb101bb
|
||||||
|
f1a1239a4487
|
||||||
|
#
|
||||||
|
b882fd4a9f78
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
43464F494D48504E4C4359454E528841 #NHIF
|
43464F494D48504E4C4359454E528841 #NHIF
|
||||||
6AC292FAA1315B4D858AB3A3D7D5933A
|
6AC292FAA1315B4D858AB3A3D7D5933A
|
||||||
404142434445464748494a4b4c4d4e4f
|
404142434445464748494a4b4c4d4e4f
|
||||||
|
3112B738D8862CCD34302EB299AAB456 # Gallagher AES (https://pastebin.com/GkbGLz8r)
|
||||||
00112233445566778899aabbccddeeff
|
00112233445566778899aabbccddeeff
|
||||||
2b7e151628aed2a6abf7158809cf4f3c
|
2b7e151628aed2a6abf7158809cf4f3c
|
||||||
fbeed618357133667c85e08f7236a8de
|
fbeed618357133667c85e08f7236a8de
|
||||||
|
|
|
@ -27,6 +27,8 @@ A5B4C3D2
|
||||||
00434343
|
00434343
|
||||||
44B44CAE
|
44B44CAE
|
||||||
88661858
|
88661858
|
||||||
|
# MKF fobs
|
||||||
|
E9920427
|
||||||
# paxton bullit?
|
# paxton bullit?
|
||||||
575F4F4B
|
575F4F4B
|
||||||
#
|
#
|
||||||
|
|
|
@ -32,4 +32,4 @@ rm $2
|
||||||
echo "hf mf eclr" >> $2
|
echo "hf mf eclr" >> $2
|
||||||
echo "hf mf eload" $1 >> $2
|
echo "hf mf eload" $1 >> $2
|
||||||
echo "hf mf ekeyprn" >> $2
|
echo "hf mf ekeyprn" >> $2
|
||||||
echo "hf mf sim u" `cat $1.eml | (read -n 8 uid; echo $uid)` >> $2
|
echo "hf mf sim -u" `cat $1.eml | (read -n 8 uid; echo $uid)` >> $2
|
||||||
|
|
|
@ -6,7 +6,7 @@ local ansicolors = require('ansicolors')
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = 'Martin Holst Swende'
|
author = 'Martin Holst Swende'
|
||||||
version = 'v1.0.2'
|
version = 'v1.0.3'
|
||||||
desc = [[
|
desc = [[
|
||||||
This script takes a dumpfile from 'hf mf dump' and converts it to a format that can be used
|
This script takes a dumpfile from 'hf mf dump' and converts it to a format that can be used
|
||||||
by the emulator
|
by the emulator
|
||||||
|
@ -46,7 +46,7 @@ end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR:', err)
|
print('[!!] ERROR:', err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
|
@ -115,8 +115,7 @@ local function main(args)
|
||||||
|
|
||||||
local dumpdata = readdump(infile)
|
local dumpdata = readdump(infile)
|
||||||
-- The hex-data is now in ascii-format,
|
-- The hex-data is now in ascii-format,
|
||||||
if dumpdata == NIL then return oops('Dumpfle not loaded') end
|
if dumpdata == nil then return oops('Dumpfle not loaded') end
|
||||||
|
|
||||||
|
|
||||||
-- But first, check the uid
|
-- But first, check the uid
|
||||||
local uid = string.sub(dumpdata, 1, 8)
|
local uid = string.sub(dumpdata, 1, 8)
|
||||||
|
@ -124,8 +123,7 @@ local function main(args)
|
||||||
|
|
||||||
-- Format some linebreaks
|
-- Format some linebreaks
|
||||||
dumpdata = convert_to_emulform(dumpdata)
|
dumpdata = convert_to_emulform(dumpdata)
|
||||||
if dumpdata == NIL then return oops('Dumpfle not loaded') end
|
if dumpdata == nil then return oops('Dumpfle not loaded') end
|
||||||
|
|
||||||
|
|
||||||
local outfile = io.open(output, 'w')
|
local outfile = io.open(output, 'w')
|
||||||
if outfile == nil then
|
if outfile == nil then
|
||||||
|
@ -134,7 +132,7 @@ local function main(args)
|
||||||
|
|
||||||
outfile:write(dumpdata:lower())
|
outfile:write(dumpdata:lower())
|
||||||
io.close(outfile)
|
io.close(outfile)
|
||||||
print(('Wrote an emulator-dump to the file %s'):format(output))
|
print(('[+] Wrote an emulator-dump to the file %s'):format(output))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ local ansicolors = require('ansicolors')
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = 'Martin Holst Swende'
|
author = 'Martin Holst Swende'
|
||||||
version = 'v1.0.2'
|
version = 'v1.0.3'
|
||||||
desc =[[
|
desc =[[
|
||||||
This script takes a dumpfile and produces a html based dump, which is a
|
This script takes a dumpfile and produces a html based dump, which is a
|
||||||
bit more easily analyzed.
|
bit more easily analyzed.
|
||||||
|
@ -45,7 +45,7 @@ end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR:', err)
|
print('[!!] ERROR:', err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
|
@ -76,7 +76,7 @@ local function main(args)
|
||||||
local filename, err = dumplib.convert_bin_to_html(input,output, 16)
|
local filename, err = dumplib.convert_bin_to_html(input,output, 16)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
print(('Wrote a HTML dump to the file %s'):format(filename))
|
print(('[+] Wrote a HTML dump to the file %s'):format(filename))
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
|
|
|
@ -5,7 +5,7 @@ local ansicolors = require('ansicolors')
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = 'Iceman'
|
author = 'Iceman'
|
||||||
version = 'v1.0.2'
|
version = 'v1.0.3'
|
||||||
desc =[[
|
desc =[[
|
||||||
This script takes an dumpfile in EML (ASCII) format and converts it to the PM3 dumpbin file to be used with `hf mf restore`
|
This script takes an dumpfile in EML (ASCII) format and converts it to the PM3 dumpbin file to be used with `hf mf restore`
|
||||||
]]
|
]]
|
||||||
|
@ -40,7 +40,7 @@ end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR:', err)
|
print('[!!] ERROR:', err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
|
@ -82,7 +82,7 @@ local function main(args)
|
||||||
local filename, err = dumplib.convert_eml_to_bin(input,output)
|
local filename, err = dumplib.convert_eml_to_bin(input,output)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
ExitMsg(('Wrote a BIN dump to the file %s'):format(filename))
|
ExitMsg(('[+] Wrote a BIN dump to the file %s'):format(filename))
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|
|
@ -7,7 +7,7 @@ local ansicolors = require('ansicolors')
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = 'Martin Holst Swende'
|
author = 'Martin Holst Swende'
|
||||||
version = 'v1.0.2'
|
version = 'v1.0.3'
|
||||||
desc = [[
|
desc = [[
|
||||||
This script takes a dumpfile on EML (ASCII) format and produces a html based dump, which is a
|
This script takes a dumpfile on EML (ASCII) format and produces a html based dump, which is a
|
||||||
bit more easily analyzed.
|
bit more easily analyzed.
|
||||||
|
@ -44,7 +44,7 @@ end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR:', err)
|
print('[!!] ERROR:', err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
|
@ -75,7 +75,7 @@ local function main(args)
|
||||||
local filename, err = dumplib.convert_eml_to_html(input,output)
|
local filename, err = dumplib.convert_eml_to_html(input,output)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
|
|
||||||
print(('Wrote a HTML dump to the file %s'):format(filename))
|
print(('[+] Wrote a HTML dump to the file %s'):format(filename))
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
|
|
|
@ -6,16 +6,16 @@ local ansicolors = require('ansicolors')
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = "Martin Holst Swende \n @Marshmellow \n @iceman"
|
author = "Martin Holst Swende \n @Marshmellow \n @iceman"
|
||||||
version = 'v1.0.2'
|
version = 'v1.0.4'
|
||||||
desc =[[
|
desc =[[
|
||||||
This script takes a dumpfile from 'hf mfu dump' and converts it to a format that can be used
|
This script takes a dumpfile from 'hf mfu dump' and converts it to a format that can be used
|
||||||
by the emulator
|
by the emulator
|
||||||
]]
|
]]
|
||||||
example = [[
|
example = [[
|
||||||
script run hf_mfu_dumptoemulator -i dumpdata-foobar.bin
|
script run data_mfu_bin2eml -i dumpdata-foobar.bin
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run hf_mfu_dumptoemulator [-i <file>] [-o <file>]
|
script run data_mfu_bin2eml [-i <file>] [-o <file>]
|
||||||
]]
|
]]
|
||||||
arguments = [[
|
arguments = [[
|
||||||
-h This help
|
-h This help
|
||||||
|
@ -43,7 +43,7 @@ end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
local function oops(err)
|
local function oops(err)
|
||||||
print('ERROR:', err)
|
print('[!!] ERROR:', err)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
|
@ -133,7 +133,7 @@ local function main(args)
|
||||||
|
|
||||||
outfile:write(dumpdata:lower())
|
outfile:write(dumpdata:lower())
|
||||||
io.close(outfile)
|
io.close(outfile)
|
||||||
print(('Wrote an emulator-dump to the file %s'):format(output))
|
print(('[+] Wrote an emulator-dump to the file %s'):format(output))
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
|
@ -582,14 +582,14 @@ function writeToTag(tag)
|
||||||
-- write pm3-buffer to Tag
|
-- write pm3-buffer to Tag
|
||||||
for i=1, WriteBytes do
|
for i=1, WriteBytes do
|
||||||
if (i > 7) then
|
if (i > 7) then
|
||||||
cmd = ("hf legic wrbl o %02x d %s "):format(i-1, padString(bytes[i]))
|
cmd = ("hf legic wrbl -o %d -d %s "):format(i-1, padString(bytes[i]))
|
||||||
print(acgreen..cmd..acoff)
|
print(acgreen..cmd..acoff)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
elseif (i == 7) then
|
elseif (i == 7) then
|
||||||
if (writeDCF) then
|
if (writeDCF) then
|
||||||
-- write DCF in reverse order (requires 'mosci-patch')
|
-- write DCF in reverse order (requires 'mosci-patch')
|
||||||
cmd = ('hf legic wrbl o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
|
cmd = ('hf legic wrbl -o 5 -d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
|
||||||
print(acgreen..cmd..acoff)
|
print(acgreen..cmd..acoff)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
@ -704,13 +704,32 @@ function writeFile(bytes, filename)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function getRandomTempName()
|
||||||
|
local upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
local lowerCase = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
local characterSet = upperCase .. lowerCase
|
||||||
|
|
||||||
|
local keyLength = 8
|
||||||
|
local output = ""
|
||||||
|
|
||||||
|
for i = 1, keyLength do
|
||||||
|
local rand = math.random(#characterSet)
|
||||||
|
output = output .. string.sub(characterSet, rand, rand)
|
||||||
|
end
|
||||||
|
|
||||||
|
output = "hf-legic-temp-" .. output
|
||||||
|
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- read from pm3 into virtual-tag
|
-- read from pm3 into virtual-tag
|
||||||
function readFromPM3()
|
function readFromPM3()
|
||||||
local tag, bytes, infile
|
local tag, bytes, infile
|
||||||
--infile="legic.temp"
|
--infile="legic.temp"
|
||||||
infile=os.tmpname()
|
infile=getRandomTempName()
|
||||||
core.console("hf legic dump f "..infile)
|
core.console("hf legic dump -f "..infile)
|
||||||
tag=readFile(infile..".bin")
|
tag=readFile(infile..".bin")
|
||||||
os.remove(infile)
|
os.remove(infile)
|
||||||
os.remove(infile..".bin")
|
os.remove(infile..".bin")
|
||||||
|
|
|
@ -456,7 +456,7 @@ local function writeToTag(plainBytes)
|
||||||
-- write data to file
|
-- write data to file
|
||||||
if (writeOutputBytes(bytes, "hf-legic-UID-dump.bin")) then
|
if (writeOutputBytes(bytes, "hf-legic-UID-dump.bin")) then
|
||||||
-- write pm3-buffer to Tag
|
-- write pm3-buffer to Tag
|
||||||
cmd = ('hf legic restore f hf-legic-UID-dump')
|
cmd = ('hf legic restore -f hf-legic-UID-dump')
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -530,13 +530,13 @@ local function main(args)
|
||||||
res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:"
|
res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:"
|
||||||
res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc, -2)
|
res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc, -2)
|
||||||
res = res .."\nyou may load the new file with:"
|
res = res .."\nyou may load the new file with:"
|
||||||
res = res ..ansicolors.yellow.."hf legic eload f "..outfile..ansicolors.reset
|
res = res ..ansicolors.yellow.."hf legic eload -f "..outfile..ansicolors.reset
|
||||||
res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC"
|
res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC"
|
||||||
res = res .."\nafter writing this dump to a tag!"
|
res = res .."\nafter writing this dump to a tag!"
|
||||||
res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3, Segment-Header0..3"
|
res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3, Segment-Header0..3"
|
||||||
res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):"
|
res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):"
|
||||||
res = res .."\n"
|
res = res .."\n"
|
||||||
res = res ..ansicolors.yellow.."hf legic crc d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." u "..newcrc.." c 8"..ansicolors.reset
|
res = res ..ansicolors.yellow.."hf legic crc -d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." --mcc "..newcrc.." -t 8"..ansicolors.reset
|
||||||
-- this can not be calculated without knowing the new MCD, MSN0..2
|
-- this can not be calculated without knowing the new MCD, MSN0..2
|
||||||
print(res)
|
print(res)
|
||||||
end
|
end
|
||||||
|
|
|
@ -99,7 +99,7 @@ local function nested(key,sak)
|
||||||
else
|
else
|
||||||
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
||||||
end
|
end
|
||||||
local cmd = string.format('hf mf nested %d 0 A %s d', typ, key)
|
local cmd = string.format('hf mf nested -t %d -b 0 --keya -k %s --dumpkeys', typ, key)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ local function dump_tag(uid, numsectors)
|
||||||
|
|
||||||
local dumpfile = 'hf-mf-'..uid..'-dump'
|
local dumpfile = 'hf-mf-'..uid..'-dump'
|
||||||
|
|
||||||
local dmp = ('hf mf dump %s f %s'):format(typ, dumpfile)
|
local dmp = ('hf mf dump -t %s -f %s'):format(typ, dumpfile)
|
||||||
core.console(dmp)
|
core.console(dmp)
|
||||||
|
|
||||||
-- Save the global args, those are *our* arguments
|
-- Save the global args, those are *our* arguments
|
||||||
|
|
|
@ -14,7 +14,7 @@ This script will generate 'hf mf wrbl' commands for each block to format a Mifar
|
||||||
Alla datablocks gets 0x00
|
Alla datablocks gets 0x00
|
||||||
As default the script sets the keys A/B to 0xFFFFFFFFFFFF
|
As default the script sets the keys A/B to 0xFFFFFFFFFFFF
|
||||||
and the access bytes will become 0x78,0x77,0x88
|
and the access bytes will become 0x78,0x77,0x88
|
||||||
The GDB will become 0x00
|
The GPB will become 0x00
|
||||||
|
|
||||||
The script will skip the manufactoring block 0.
|
The script will skip the manufactoring block 0.
|
||||||
]]
|
]]
|
||||||
|
@ -169,7 +169,7 @@ local function main(args)
|
||||||
GetCardInfo()
|
GetCardInfo()
|
||||||
|
|
||||||
-- Show info
|
-- Show info
|
||||||
print( string.format('Estimating number of blocks: %d', numBlocks))
|
print( string.format('Estimating number of blocks: %d', numBlocks + 1))
|
||||||
print( string.format('Old key: %s', OldKey))
|
print( string.format('Old key: %s', OldKey))
|
||||||
print( string.format('New key: %s', NewKey))
|
print( string.format('New key: %s', NewKey))
|
||||||
print( string.format('New Access: %s', Accessbytes))
|
print( string.format('New Access: %s', Accessbytes))
|
||||||
|
|
|
@ -147,7 +147,7 @@ local function main(args)
|
||||||
|
|
||||||
--Trying to find the other keys
|
--Trying to find the other keys
|
||||||
if useNested then
|
if useNested then
|
||||||
core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
|
core.console( ('hf mf nested -t 1 -b 0 --keya -k %s --dumpkeys'):format(keyA) )
|
||||||
end
|
end
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
|
@ -496,7 +496,7 @@ local function main(args)
|
||||||
err = LoadEmulator(uid, blocks)
|
err = LoadEmulator(uid, blocks)
|
||||||
if err then return oops(err) end
|
if err then return oops(err) end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--')
|
print('The simulation is now prepared.\n --> run \"hf mf sim -u '..uid..'\" <--')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
|
|
|
@ -99,10 +99,10 @@ local function main(args)
|
||||||
local command = ''
|
local command = ''
|
||||||
|
|
||||||
if mftype == 'mfc' then
|
if mftype == 'mfc' then
|
||||||
command = 'hf 14a sim t 1 u %014x'
|
command = 'hf 14a sim -t 1 -u %014x'
|
||||||
msg('Bruteforcing Mifare Classic card numbers')
|
msg('Bruteforcing Mifare Classic card numbers')
|
||||||
elseif mftype == 'mfu' then
|
elseif mftype == 'mfu' then
|
||||||
command = 'hf 14a sim t 2 u %014x'
|
command = 'hf 14a sim -t 2 -u %014x'
|
||||||
msg('Bruteforcing Mifare Ultralight card numbers')
|
msg('Bruteforcing Mifare Ultralight card numbers')
|
||||||
else
|
else
|
||||||
return print(usage)
|
return print(usage)
|
||||||
|
|
|
@ -44,8 +44,8 @@ arguments = [[
|
||||||
-c read magic configuration
|
-c read magic configuration
|
||||||
-u UID (14 hexsymbols), set UID on tag
|
-u UID (14 hexsymbols), set UID on tag
|
||||||
-t tag type to impersonate
|
-t tag type to impersonate
|
||||||
1 = UL_EV1 48k
|
1 = UL EV1 48b
|
||||||
2 = UL_EV1 128k
|
2 = UL EV1 128b
|
||||||
3 = NTAG 210
|
3 = NTAG 210
|
||||||
4 = NTAG 212
|
4 = NTAG 212
|
||||||
5 = NTAG 213 (true)
|
5 = NTAG 213 (true)
|
||||||
|
@ -60,7 +60,7 @@ arguments = [[
|
||||||
-p password (8 hexsymbols), set password on tag.
|
-p password (8 hexsymbols), set password on tag.
|
||||||
-a pack ( 4 hexsymbols), set pack on tag.
|
-a pack ( 4 hexsymbols), set pack on tag.
|
||||||
-s signature data (64 hexsymbols), set signature data on tag.
|
-s signature data (64 hexsymbols), set signature data on tag.
|
||||||
-o OTP data (8 hexsymbols), set one-time-pad data on tag.
|
-o OTP data (8 hexsymbols), set `One-Time Programmable` data on tag.
|
||||||
-v version data (16 hexsymbols), set version data on tag.
|
-v version data (16 hexsymbols), set version data on tag.
|
||||||
-w wipe tag. You can specify password if the tag has been locked down. Fills tag with zeros and put default values for NTAG213 (like -t 5)
|
-w wipe tag. You can specify password if the tag has been locked down. Fills tag with zeros and put default values for NTAG213 (like -t 5)
|
||||||
-k pwd to use with the wipe option
|
-k pwd to use with the wipe option
|
||||||
|
|
|
@ -4,26 +4,32 @@ local ansicolors = require('ansicolors')
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = "Iceman"
|
author = "Iceman"
|
||||||
version = 'v1.0.2'
|
version = 'v1.0.3'
|
||||||
desc = [[
|
desc = [[
|
||||||
This script tries to set UID on a mifare Ultralight magic card which either
|
This script tries to set UID on a mifare Ultralight magic card which either
|
||||||
- answers to chinese backdoor commands
|
- answers to chinese backdoor commands
|
||||||
- brickable magic tag (must write in one session)
|
- brickable magic tag (must write in one session)
|
||||||
|
|
||||||
|
It defaults to GEN1A type of uid changeable card.
|
||||||
]]
|
]]
|
||||||
example = [[
|
example = [[
|
||||||
-- backdoor magic tag
|
-- backdoor magic tag (gen1a)
|
||||||
script run hf_mfu_setuid -u 11223344556677
|
script run hf_mfu_setuid -u 11223344556677
|
||||||
|
|
||||||
-- brickable magic tag
|
-- backdoor magic tag (gen1b)
|
||||||
script run hf_mfu_setuid -b -u 11223344556677
|
script run hf_mfu_setuid -b -u 11223344556677
|
||||||
|
|
||||||
|
-- brickable magic tag (gen2)
|
||||||
|
script run hf_mfu_setuid -2 -u 11223344556677
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run hf_mfu_setuid [-h] [-b] [-u <uid>]
|
script run hf_mfu_setuid [-h] [-b] [-2] [-u <uid>]
|
||||||
]]
|
]]
|
||||||
arguments = [[
|
arguments = [[
|
||||||
-h : this help
|
-h : this help
|
||||||
-u <UID> : UID (14 hexsymbols)
|
-u <UID> : UID (14 hexsymbols)
|
||||||
-b : write to brickable magic tag
|
-b : write to magic tag GEN1B
|
||||||
|
-2 : write to brickable magic tag GEN2
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
|
@ -65,23 +71,33 @@ local function help()
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
--- Set UID on magic command enabled
|
--- Set UID on magic command enabled
|
||||||
function magicUID(b0, b1, b2)
|
function magicUID(b0, b1, b2, isgen1a)
|
||||||
|
|
||||||
print('Using backdoor Magic tag function')
|
if isgen1a then
|
||||||
|
print('Using backdoor Magic tag (gen1a) function')
|
||||||
|
else
|
||||||
|
print('Using backdoor Magic tag (gen1b) function')
|
||||||
|
end
|
||||||
|
|
||||||
-- write block 0
|
-- write block 0
|
||||||
core.console('hf 14a raw -k -a -b 7 40')
|
core.console('hf 14a raw -k -a -b 7 40')
|
||||||
|
if isgen1a then
|
||||||
core.console('hf 14a raw -k -a 43')
|
core.console('hf 14a raw -k -a 43')
|
||||||
|
end
|
||||||
core.console('hf 14a raw -c -a A200'..b0)
|
core.console('hf 14a raw -c -a A200'..b0)
|
||||||
|
|
||||||
-- write block 1
|
-- write block 1
|
||||||
core.console('hf 14a raw -k -a -b 7 40')
|
core.console('hf 14a raw -k -a -b 7 40')
|
||||||
|
if isgen1a then
|
||||||
core.console('hf 14a raw -k -a 43')
|
core.console('hf 14a raw -k -a 43')
|
||||||
|
end
|
||||||
core.console('hf 14a raw -c -a A201'..b1)
|
core.console('hf 14a raw -c -a A201'..b1)
|
||||||
|
|
||||||
-- write block 2
|
-- write block 2
|
||||||
core.console('hf 14a raw -k -a -b 7 40')
|
core.console('hf 14a raw -k -a -b 7 40')
|
||||||
|
if isgen1a then
|
||||||
core.console('hf 14a raw -k -a 43')
|
core.console('hf 14a raw -k -a 43')
|
||||||
|
end
|
||||||
core.console('hf 14a raw -c -a A202'..b2)
|
core.console('hf 14a raw -c -a A202'..b2)
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
|
@ -113,10 +129,11 @@ function main(args)
|
||||||
local tagtype = 1
|
local tagtype = 1
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'hu:b') do
|
for o, a in getopt.getopt(args, 'hu:b2') do
|
||||||
if o == 'h' then return help() end
|
if o == 'h' then return help() end
|
||||||
if o == 'u' then uid = a end
|
if o == 'u' then uid = a end
|
||||||
if o == 'b' then tagtype = 2 end
|
if o == 'b' then tagtype = 2 end
|
||||||
|
if o == '2' then tagtype = 3 end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- uid string checks
|
-- uid string checks
|
||||||
|
@ -137,10 +154,11 @@ function main(args)
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
if tagtype == 2 then
|
if tagtype == 3 then
|
||||||
brickableUID(block0, block1, block2)
|
brickableUID(block0, block1, block2)
|
||||||
else
|
else
|
||||||
magicUID(block0, block1, block2)
|
local is_gen1a = (tagtype == 1)
|
||||||
|
magicUID(block0, block1, block2, is_gen1a)
|
||||||
end
|
end
|
||||||
|
|
||||||
--halt
|
--halt
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
local getopt = require('getopt')
|
local getopt = require('getopt')
|
||||||
local ansicolors = require('ansicolors')
|
local ansicolors = require('ansicolors')
|
||||||
|
local utils = require('utils')
|
||||||
|
|
||||||
copyright = 'Copyright (c) 2019 IceSQL AB. All rights reserved.'
|
copyright = 'Copyright (c) 2019 IceSQL AB. All rights reserved.'
|
||||||
author = 'Christian Herrmann'
|
author = 'Christian Herrmann'
|
||||||
version = 'v1.0.1'
|
version = 'v1.0.3'
|
||||||
desc = [[
|
desc = [[
|
||||||
This script initialize a Proxmark3 RDV4.0 with
|
This script initialize a Proxmark3 RDV4.0 with
|
||||||
- uploading dictionary files to flashmem
|
- uploading dictionary files to flashmem
|
||||||
|
@ -82,10 +83,14 @@ function main(args)
|
||||||
-- T55x7 Device configuration
|
-- T55x7 Device configuration
|
||||||
print('Configure T55XX device side to match RDV4')
|
print('Configure T55XX device side to match RDV4')
|
||||||
print(dash)
|
print(dash)
|
||||||
core.console('lf t55xx deviceconfig r 0 a 29 b 17 c 15 d 47 e 15 p')
|
core.console('lf t55xx deviceconfig --r0 -a 29 -b 17 -c 15 -d 47 -e 15 -p')
|
||||||
core.console('lf t55xx deviceconfig r 1 a 29 b 17 c 18 d 50 e 15 p')
|
utils.Sleep(1)
|
||||||
core.console('lf t55xx deviceconfig r 2 a 29 b 17 c 18 d 40 e 15 p')
|
core.console('lf t55xx deviceconfig --r1 -a 29 -b 17 -c 18 -d 50 -e 15 -p')
|
||||||
core.console('lf t55xx deviceconfig r 3 a 29 b 17 c 15 d 31 e 15 f 47 g 63 p')
|
utils.Sleep(1)
|
||||||
|
core.console('lf t55xx deviceconfig --r2 -a 29 -b 17 -c 18 -d 40 -e 15 -p')
|
||||||
|
utils.Sleep(1)
|
||||||
|
core.console('lf t55xx deviceconfig --r3 -a 29 -b 17 -c 15 -d 31 -e 15 -f 47 -g 63 -p')
|
||||||
|
utils.Sleep(1)
|
||||||
|
|
||||||
print('')
|
print('')
|
||||||
print('')
|
print('')
|
||||||
|
|
212
client/luascripts/lf_em4100_bulk.lua
Normal file
212
client/luascripts/lf_em4100_bulk.lua
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
local getopt = require('getopt')
|
||||||
|
local utils = require('utils')
|
||||||
|
local ac = require('ansicolors')
|
||||||
|
|
||||||
|
copyright = ''
|
||||||
|
author = "Christian Herrmann"
|
||||||
|
version = 'v1.0.2'
|
||||||
|
desc = [[
|
||||||
|
Perform bulk EM410x enrollment of T5577 RFID tags. It keeps track of last card id used.
|
||||||
|
If called with -s, this value resets "session".
|
||||||
|
|
||||||
|
if press <enter> it defaults to Y, which writes a ID.
|
||||||
|
Any other input char will exit the script.
|
||||||
|
|
||||||
|
You can supply a password, which will set the config block / block 7 on the T5577.
|
||||||
|
|
||||||
|
The verify option will issue a 'lf em 410x reader' command, so you can manually verify
|
||||||
|
that the write worked.
|
||||||
|
|
||||||
|
]]
|
||||||
|
example = [[
|
||||||
|
-- resets and start enrolling EM410x id 11CC334455
|
||||||
|
script run lf_em4100_bulk.lua -s 11CC334455
|
||||||
|
|
||||||
|
-- continue enrolling from where last iteration
|
||||||
|
script run lf_em4100_bulk.lua -c
|
||||||
|
|
||||||
|
-- reset and start enrolling from 11223344,
|
||||||
|
-- protecting the tag with password 010203
|
||||||
|
-- and verify the em id write.
|
||||||
|
script run lf_em4100_bulk.lua -s 1122334455 -p 01020304 -v
|
||||||
|
]]
|
||||||
|
usage = [[
|
||||||
|
script run lf_en4100_bulk.lua [-h] [-c] [-p password] [-s <start cn>] [-v]
|
||||||
|
]]
|
||||||
|
arguments = [[
|
||||||
|
-h : this help
|
||||||
|
-c : continue from last card number used
|
||||||
|
-p : Password protecting the T5577.
|
||||||
|
-s : starting card number
|
||||||
|
-v : verify write by executing a `lf em 410x reader`
|
||||||
|
]]
|
||||||
|
|
||||||
|
-- Some globals
|
||||||
|
local DEBUG = false
|
||||||
|
local ENROLL_STATUS_FN = 'lf_em4100_status.txt'
|
||||||
|
---
|
||||||
|
-- A debug printout-function
|
||||||
|
local function dbg(args)
|
||||||
|
if not DEBUG then return end
|
||||||
|
if type(args) == 'table' then
|
||||||
|
local i = 1
|
||||||
|
while args[i] do
|
||||||
|
dbg(args[i])
|
||||||
|
i = i+1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print('###', args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- This is only meant to be used when errors occur
|
||||||
|
local function oops(err)
|
||||||
|
print('ERROR:', err)
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
return nil, errr
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- Usage help
|
||||||
|
local function help()
|
||||||
|
print(copyright)
|
||||||
|
print(author)
|
||||||
|
print(version)
|
||||||
|
print(desc)
|
||||||
|
print(ac.cyan..'Usage'..ac.reset)
|
||||||
|
print(usage)
|
||||||
|
print(ac.cyan..'Arguments'..ac.reset)
|
||||||
|
print(arguments)
|
||||||
|
print(ac.cyan..'Example usage'..ac.reset)
|
||||||
|
print(example)
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- Exit message
|
||||||
|
local function exitMsg(msg)
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print(msg)
|
||||||
|
print()
|
||||||
|
end
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function readfile()
|
||||||
|
local f = io.open(ENROLL_STATUS_FN, "r")
|
||||||
|
if f == nil then
|
||||||
|
return nil, string.format("Could not read file %s", ENROLL_STATUS_FN)
|
||||||
|
end
|
||||||
|
local t = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
local cn_hi = tonumber(t:sub(1, 2), 16)
|
||||||
|
local cn_low = tonumber(t:sub(3, 10), 16)
|
||||||
|
print(('Using EM4100 ID '..ac.green..'%02X%08X'..ac.reset..' from `'..ac.yellow..'%s'..ac.reset..'`'):format(cn_hi, cn_low, ENROLL_STATUS_FN))
|
||||||
|
return cn_hi, cn_low
|
||||||
|
end
|
||||||
|
---
|
||||||
|
--
|
||||||
|
local function writefile(cn_hi, cn_low)
|
||||||
|
local f = io.open(ENROLL_STATUS_FN, "w")
|
||||||
|
if f == nil then
|
||||||
|
return nil, string.format("Could not write to file %s", ENROLL_STATUS_FN)
|
||||||
|
end
|
||||||
|
f:write(("%02X%08X\n"):format(cn_hi, cn_low))
|
||||||
|
f:close()
|
||||||
|
print(('Wrote EM4100 ID '..ac.green..'%02X%08X'..ac.reset..' to `'..ac.yellow..'%s'..ac.reset..'`'):format(cn_hi, cn_low, ENROLL_STATUS_FN))
|
||||||
|
return true, 'Ok'
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- main
|
||||||
|
local function main(args)
|
||||||
|
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print()
|
||||||
|
|
||||||
|
if #args == 0 then return help() end
|
||||||
|
|
||||||
|
local shall_verify = false
|
||||||
|
local shall_continue = false
|
||||||
|
local got_pwd = false
|
||||||
|
local startid = ''
|
||||||
|
local ipwd = ''
|
||||||
|
|
||||||
|
|
||||||
|
for o, a in getopt.getopt(args, 'cp:s:hv') do
|
||||||
|
if o == 'h' then return help() end
|
||||||
|
if o == 'c' then shall_continue = true end
|
||||||
|
if o == 's' then startid = a end
|
||||||
|
if o == 'p' then
|
||||||
|
ipwd = a
|
||||||
|
got_pwd = true
|
||||||
|
end
|
||||||
|
if o == 'v' then shall_verify = true end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- if reset/start over, check -s
|
||||||
|
if not shall_continue then
|
||||||
|
if startid == nil then return oops('empty card number string') end
|
||||||
|
if #startid == 0 then return oops('empty card number string') end
|
||||||
|
if #startid ~= 10 then return oops('card number wrong length. Must be 5 hex bytes') end
|
||||||
|
end
|
||||||
|
|
||||||
|
if got_pwd then
|
||||||
|
if ipwd == nil then return oops('empty password') end
|
||||||
|
if #ipwd == 0 then return oops('empty password') end
|
||||||
|
if #ipwd ~= 8 then return oops('password wrong length. Must be 4 hex bytes') end
|
||||||
|
end
|
||||||
|
|
||||||
|
core.console('clear')
|
||||||
|
print(ac.red..'disable hints for less output'..ac.reset)
|
||||||
|
core.console('pref set hint --off')
|
||||||
|
print('')
|
||||||
|
|
||||||
|
local hi = tonumber(startid:sub(1, 2), 16)
|
||||||
|
local low = tonumber(startid:sub(3, 10), 16)
|
||||||
|
local pwd = tonumber(ipwd, 16)
|
||||||
|
|
||||||
|
if got_pwd then
|
||||||
|
print(('Will protect T5577 with password '..ac.green..'%08X'..ac.reset):format(pwd))
|
||||||
|
end
|
||||||
|
|
||||||
|
if shall_verify then
|
||||||
|
print('Will verify write afterwards')
|
||||||
|
end
|
||||||
|
|
||||||
|
if shall_continue then
|
||||||
|
print('Continue enrolling from last save')
|
||||||
|
hi, low = readfile()
|
||||||
|
else
|
||||||
|
print('reset & starting enrolling from refresh')
|
||||||
|
end
|
||||||
|
|
||||||
|
local template = 'EM4100 ID '..ac.green..'%02X%08X'..ac.reset
|
||||||
|
for i = low, low + 10000, 1 do
|
||||||
|
print('')
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
local msg = (template):format(hi, i)
|
||||||
|
local ans = utils.input(msg, 'y'):lower()
|
||||||
|
if ans == 'y' then
|
||||||
|
core.console( ('lf em 410x clone --id %02X%08X'):format(hi, i) )
|
||||||
|
-- print ( ('lf em 410x clone --id %02X%08X'):format(hi, i) )
|
||||||
|
|
||||||
|
if got_pwd then
|
||||||
|
core.console('lf t55 detect')
|
||||||
|
core.console(('lf t55 protect -n %08x'):format(pwd))
|
||||||
|
end
|
||||||
|
|
||||||
|
if shall_verify then
|
||||||
|
core.console('lf em 410x reader')
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print(ac.red..'User aborted'..ac.reset)
|
||||||
|
low = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
writefile(hi, low)
|
||||||
|
|
||||||
|
print('enabling hints again')
|
||||||
|
core.console('pref set hint --on')
|
||||||
|
end
|
||||||
|
|
||||||
|
main(args)
|
104
client/luascripts/ntag_getsig.lua
Normal file
104
client/luascripts/ntag_getsig.lua
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
local getopt = require('getopt')
|
||||||
|
local lib14a = require('read14a')
|
||||||
|
local cmds = require('commands')
|
||||||
|
local ansicolors = require('ansicolors')
|
||||||
|
|
||||||
|
copyright = 'Copyright 2021 A. Ozkal, released under GPLv2+.'
|
||||||
|
author = 'Ave'
|
||||||
|
version = 'v1.0.0'
|
||||||
|
desc = [[
|
||||||
|
This script attempts to grab signatures from an NTAG or MFULEV1 card and print it in a machine parsable way
|
||||||
|
]]
|
||||||
|
example = [[
|
||||||
|
script run ntag_getsig
|
||||||
|
]]
|
||||||
|
usage = [[
|
||||||
|
script run ntag_getsig [-h]
|
||||||
|
]]
|
||||||
|
arguments = [[
|
||||||
|
-h : This help
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function help()
|
||||||
|
print(author)
|
||||||
|
print(version)
|
||||||
|
print(desc)
|
||||||
|
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||||
|
print(usage)
|
||||||
|
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||||
|
print(arguments)
|
||||||
|
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||||
|
print(example)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Used to send raw data to the firmware to subsequently forward the data to the card.
|
||||||
|
-- from mifareplus.lua
|
||||||
|
local function sendRaw(rawdata, crc, power)
|
||||||
|
-- print(("<sent>: %s"):format(rawdata))
|
||||||
|
|
||||||
|
local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW
|
||||||
|
if crc then
|
||||||
|
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
|
||||||
|
end
|
||||||
|
if power then
|
||||||
|
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
|
||||||
|
end
|
||||||
|
|
||||||
|
local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER,
|
||||||
|
arg1 = flags, -- Send raw
|
||||||
|
arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata
|
||||||
|
data = rawdata
|
||||||
|
}
|
||||||
|
local ignore_response = false
|
||||||
|
local result, err = command:sendMIX(ignore_response)
|
||||||
|
if result then
|
||||||
|
--unpack the first 4 parts of the result as longs, and the last as an extremely long string to later be cut down based on arg1, the number of bytes returned
|
||||||
|
local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',result)
|
||||||
|
|
||||||
|
returned_bytes = string.sub(data, 1, arg1 * 2)
|
||||||
|
if #returned_bytes > 0 then
|
||||||
|
-- print(("<recvd>: %s"):format(returned_bytes)) -- need to multiply by 2 because the hex digits are actually two bytes when they are strings
|
||||||
|
return returned_bytes
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("Error sending the card raw data.")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- The main entry point
|
||||||
|
function main(args)
|
||||||
|
-- Read the parameters
|
||||||
|
for o, a in getopt.getopt(args, 'h') do
|
||||||
|
if o == 'h' then return help() end
|
||||||
|
end
|
||||||
|
|
||||||
|
local tag, err = lib14a.read(true, false)
|
||||||
|
|
||||||
|
if not err then
|
||||||
|
local sig = sendRaw("3C00", true, true)
|
||||||
|
local ver = sendRaw("60", true, false)
|
||||||
|
if sig and ver then -- if false, that's a fail right there
|
||||||
|
sig = string.sub(sig, 0, -5)
|
||||||
|
ver = string.sub(ver, 0, -5)
|
||||||
|
local text = tag.name..","..ver..","..tag.uid..","..sig
|
||||||
|
print(text)
|
||||||
|
|
||||||
|
local filename = "originalitysig.csv"
|
||||||
|
local outfile = io.open(filename, "a")
|
||||||
|
if outfile ~= nil then
|
||||||
|
outfile:write(text.."\n")
|
||||||
|
io.close(outfile)
|
||||||
|
else
|
||||||
|
print(ansicolors.red.."Couldn't open file originalitysig.csv."..ansicolors.reset)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print(ansicolors.red.."Read FAILED."..ansicolors.reset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
main(args)
|
|
@ -7,11 +7,11 @@ local ansicolors = require('ansicolors')
|
||||||
|
|
||||||
copyright = ''
|
copyright = ''
|
||||||
author = 'Iceman'
|
author = 'Iceman'
|
||||||
version = 'v1.0.3'
|
version = 'v1.0.4'
|
||||||
desc = [[
|
desc = [[
|
||||||
This script will load several traces files in current working directory/traces/ folder and do
|
This script will load several traces files in current working directory/traces/ folder and do
|
||||||
"data load"
|
"data load"
|
||||||
"lf search 1 u"
|
"lf search -1u"
|
||||||
|
|
||||||
The following tracefiles will be loaded:
|
The following tracefiles will be loaded:
|
||||||
em*.pm3
|
em*.pm3
|
||||||
|
@ -109,7 +109,7 @@ local function main(args)
|
||||||
end
|
end
|
||||||
p.close();
|
p.close();
|
||||||
|
|
||||||
local cmdLFSEARCH = 'lf search 1 u'
|
local cmdLFSEARCH = 'lf search -1u'
|
||||||
|
|
||||||
-- main loop
|
-- main loop
|
||||||
io.write('Starting to test traces > ')
|
io.write('Starting to test traces > ')
|
||||||
|
|
|
@ -4749,14 +4749,14 @@
|
||||||
"application": "Security and Access Control",
|
"application": "Security and Access Control",
|
||||||
"company": "PEC (New Zealand) Ltd.",
|
"company": "PEC (New Zealand) Ltd.",
|
||||||
"mad": "0x4811",
|
"mad": "0x4811",
|
||||||
"service_provider": "Cardax",
|
"service_provider": "Cardax / Gallagher",
|
||||||
"system_integrator": ""
|
"system_integrator": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"application": "Security and Access Control",
|
"application": "Security and Access Control",
|
||||||
"company": "PEC (New Zealand) Ltd.",
|
"company": "PEC (New Zealand) Ltd.",
|
||||||
"mad": "0x4812",
|
"mad": "0x4812",
|
||||||
"service_provider": "Cardax",
|
"service_provider": "Cardax / Gallagher",
|
||||||
"system_integrator": ""
|
"system_integrator": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -6096,6 +6096,13 @@
|
||||||
"service_provider": "CDVI",
|
"service_provider": "CDVI",
|
||||||
"system_integrator": "CDVI"
|
"system_integrator": "CDVI"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"application": "(access control and security) VIGIK",
|
||||||
|
"company": "NORALSY",
|
||||||
|
"mad": "0x4980",
|
||||||
|
"service_provider": "NORALSY",
|
||||||
|
"system_integrator": "NORALSY"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"application": "Card Administratin, cardholder adminstration, access control & security, company services, miscellaneous applications",
|
"application": "Card Administratin, cardholder adminstration, access control & security, company services, miscellaneous applications",
|
||||||
"company": "Ministry of Defense",
|
"company": "Ministry of Defense",
|
||||||
|
|
|
@ -36,7 +36,7 @@ static int openAIDFile(json_t **root, bool verbose) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) PrintAndLogEx(SUCCESS, "Loaded file (%s) OK. %zu records.", path, json_array_size(*root));
|
PrintAndLogEx(DEBUG, "Loaded file " _YELLOW_("%s") " " _GREEN_("%zu") " records ( " _GREEN_("ok") " )", path, json_array_size(*root));
|
||||||
out:
|
out:
|
||||||
free(path);
|
free(path);
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -145,22 +145,22 @@ int PrintAIDDescription(json_t *xroot, char *aid, bool verbose) {
|
||||||
const char *description = jsonStrGet(elm, "Description");
|
const char *description = jsonStrGet(elm, "Description");
|
||||||
const char *type = jsonStrGet(elm, "Type");
|
const char *type = jsonStrGet(elm, "Type");
|
||||||
|
|
||||||
if (!verbose) {
|
if (verbose == false) {
|
||||||
PrintAndLogEx(SUCCESS, "AID %s | %s | %s", vaid, vendor, name);
|
PrintAndLogEx(SUCCESS, "AID : " _YELLOW_("%s") " | %s | %s", vaid, vendor, name);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(SUCCESS, "Input AID: %s", aid);
|
PrintAndLogEx(SUCCESS, "Input AID..... " _YELLOW_("%s"), aid);
|
||||||
if (aid)
|
if (aid)
|
||||||
PrintAndLogEx(SUCCESS, "Found AID: %s", vaid);
|
PrintAndLogEx(SUCCESS, "Found AID..... " _YELLOW_("%s"), vaid);
|
||||||
if (vendor)
|
if (vendor)
|
||||||
PrintAndLogEx(SUCCESS, "Vendor: %s", vendor);
|
PrintAndLogEx(SUCCESS, "Vendor........ " _YELLOW_("%s"), vendor);
|
||||||
if (type)
|
if (type)
|
||||||
PrintAndLogEx(SUCCESS, "Type: %s", type);
|
PrintAndLogEx(SUCCESS, "Type.......... " _YELLOW_("%s"), type);
|
||||||
if (name)
|
if (name)
|
||||||
PrintAndLogEx(SUCCESS, "Name: %s", name);
|
PrintAndLogEx(SUCCESS, "Name.......... " _YELLOW_("%s"), name);
|
||||||
if (country)
|
if (country)
|
||||||
PrintAndLogEx(SUCCESS, "Country: %s", country);
|
PrintAndLogEx(SUCCESS, "Country....... %s", country);
|
||||||
if (description)
|
if (description)
|
||||||
PrintAndLogEx(SUCCESS, "Description: %s", description);
|
PrintAndLogEx(SUCCESS, "Description... %s", description);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -769,22 +769,22 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) {
|
||||||
int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) {
|
int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) {
|
||||||
//ask raw demod GraphBuffer first
|
//ask raw demod GraphBuffer first
|
||||||
|
|
||||||
uint8_t BitStream[MAX_DEMOD_BUF_LEN];
|
uint8_t bs[MAX_DEMOD_BUF_LEN];
|
||||||
size_t size = getFromGraphBuf(BitStream);
|
size_t size = getFromGraphBuf(bs);
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf");
|
PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
int startIdx = 0;
|
int startIdx = 0;
|
||||||
//invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer
|
//invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer
|
||||||
int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx);
|
int errCnt = askdemod_ext(bs, &size, &clk, &invert, maxErr, 0, 0, &startIdx);
|
||||||
if (errCnt < 0 || errCnt > maxErr) {
|
if (errCnt < 0 || errCnt > maxErr) {
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk);
|
PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
//attempt to Biphase decode BitStream
|
//attempt to Biphase decode BitStream
|
||||||
errCnt = BiphaseRawDecode(BitStream, &size, &offset, invert);
|
errCnt = BiphaseRawDecode(bs, &size, &offset, invert);
|
||||||
if (errCnt < 0) {
|
if (errCnt < 0) {
|
||||||
if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode: %d", errCnt);
|
if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode: %d", errCnt);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
@ -795,7 +795,7 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//success set DemodBuffer and return
|
//success set DemodBuffer and return
|
||||||
setDemodBuff(BitStream, size, 0);
|
setDemodBuff(bs, size, 0);
|
||||||
setClockGrid(clk, startIdx + clk * offset / 2);
|
setClockGrid(clk, startIdx + clk * offset / 2);
|
||||||
if (g_debugMode || verbose) {
|
if (g_debugMode || verbose) {
|
||||||
PrintAndLogEx(DEBUG, "Biphase Decoded using offset %d | clock %d | #errors %d | start index %d\ndata\n", offset, clk, errCnt, (startIdx + clk * offset / 2));
|
PrintAndLogEx(DEBUG, "Biphase Decoded using offset %d | clock %d | #errors %d | start index %d\ndata\n", offset, clk, errCnt, (startIdx + clk * offset / 2));
|
||||||
|
@ -1428,7 +1428,7 @@ static int CmdRawDemod(const char *Cmd) {
|
||||||
else if (str_startswith(Cmd, "am")) ans = Cmdaskmandemod(Cmd + 2);
|
else if (str_startswith(Cmd, "am")) ans = Cmdaskmandemod(Cmd + 2);
|
||||||
else if (str_startswith(Cmd, "ar")) ans = Cmdaskrawdemod(Cmd + 2);
|
else if (str_startswith(Cmd, "ar")) ans = Cmdaskrawdemod(Cmd + 2);
|
||||||
else if (str_startswith(Cmd, "nr") || Cmd[0] == 'n') ans = CmdNRZrawDemod(Cmd + 2);
|
else if (str_startswith(Cmd, "nr") || Cmd[0] == 'n') ans = CmdNRZrawDemod(Cmd + 2);
|
||||||
else if (str_startswith(Cmd, "p1") || Cmd[0] == 'p') ans = CmdPSK1rawDemod(Cmd + 2);
|
else if (str_startswith(Cmd, "p1")) ans = CmdPSK1rawDemod(Cmd + 2);
|
||||||
else if (str_startswith(Cmd, "p2")) ans = CmdPSK2rawDemod(Cmd + 2);
|
else if (str_startswith(Cmd, "p2")) ans = CmdPSK2rawDemod(Cmd + 2);
|
||||||
else PrintAndLogEx(WARNING, "Unknown modulation entered - see help ('h') for parameter structure");
|
else PrintAndLogEx(WARNING, "Unknown modulation entered - see help ('h') for parameter structure");
|
||||||
|
|
||||||
|
@ -1576,7 +1576,7 @@ int getSamplesEx(uint32_t start, uint32_t end, bool verbose) {
|
||||||
|
|
||||||
uint32_t n = end - start;
|
uint32_t n = end - start;
|
||||||
|
|
||||||
if (n <= 0 || n > pm3_capabilities.bigbuf_size - 1)
|
if (n == 0 || n > pm3_capabilities.bigbuf_size - 1)
|
||||||
n = pm3_capabilities.bigbuf_size - 1;
|
n = pm3_capabilities.bigbuf_size - 1;
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "cliparser.h"
|
#include "cliparser.h"
|
||||||
#include "pmflash.h"
|
#include "pmflash.h" // rdv40validation_t
|
||||||
#include "fileutils.h" // saveFile
|
#include "fileutils.h" // saveFile
|
||||||
#include "comms.h" // getfromdevice
|
#include "comms.h" // getfromdevice
|
||||||
#include "cmdflashmemspiffs.h" // spiffs commands
|
#include "cmdflashmemspiffs.h" // spiffs commands
|
||||||
|
@ -26,6 +26,123 @@
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
// RRG Public RSA Key
|
||||||
|
#define RRG_RSA_KEY_LEN 128
|
||||||
|
|
||||||
|
// public key Exponent E
|
||||||
|
#define RRG_RSA_E "010001"
|
||||||
|
|
||||||
|
// public key modulus N
|
||||||
|
#define RRG_RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF" \
|
||||||
|
"4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F" \
|
||||||
|
"9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33" \
|
||||||
|
"DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
|
||||||
|
|
||||||
|
// Following example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
|
||||||
|
// private key - Exponent D
|
||||||
|
#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
|
||||||
|
"66CA472BC44D253102F8B4A9D3BFA750" \
|
||||||
|
"91386C0077937FE33FA3252D28855837" \
|
||||||
|
"AE1B484A8A9A45F7EE8C0C634F99E8CD" \
|
||||||
|
"DF79C5CE07EE72C7F123142198164234" \
|
||||||
|
"CABB724CF78B8173B9F880FC86322407" \
|
||||||
|
"AF1FEDFDDE2BEB674CA15F3E81A1521E" \
|
||||||
|
"071513A1E85B5DFA031F21ECAE91A34D"
|
||||||
|
|
||||||
|
// prime P
|
||||||
|
#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
|
||||||
|
"2C01CAD19EA484A87EA4377637E75500" \
|
||||||
|
"FCB2005C5C7DD6EC4AC023CDA285D796" \
|
||||||
|
"C3D9E75E1EFC42488BB4F1D13AC30A57"
|
||||||
|
|
||||||
|
// prime Q
|
||||||
|
#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
|
||||||
|
"E211C2B9E5DB1ED0BF61D0D9899620F4" \
|
||||||
|
"910E4168387E3C30AA1E00C339A79508" \
|
||||||
|
"8452DD96A9A5EA5D9DCA68DA636032AF"
|
||||||
|
|
||||||
|
#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
|
||||||
|
"3C94D22288ACD763FD8E5600ED4A702D" \
|
||||||
|
"F84198A5F06C2E72236AE490C93F07F8" \
|
||||||
|
"3CC559CD27BC2D1CA488811730BB5725"
|
||||||
|
|
||||||
|
#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
|
||||||
|
"D8AAEA56749EA28623272E4F7D0592AF" \
|
||||||
|
"7C1F1313CAC9471B5C523BFE592F517B" \
|
||||||
|
"407A1BD76C164B93DA2D32A383E58357"
|
||||||
|
|
||||||
|
#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
|
||||||
|
"F38D18D2B2F0E2DD275AA977E2BF4411" \
|
||||||
|
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
|
||||||
|
"A74206CEC169D74BF5A8C50D6F48EA08"
|
||||||
|
|
||||||
|
int rdv4_get_signature(rdv40_validation_t *out) {
|
||||||
|
if (out == NULL) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||||
|
if (isok == false) {
|
||||||
|
PrintAndLogEx(FAILED, "fail reading from flashmemory");
|
||||||
|
return PM3_EFLASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
//rdv40_validation_t mem;
|
||||||
|
memcpy(out, (rdv40_validation_t *)resp.data.asBytes, sizeof(rdv40_validation_t));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate signature
|
||||||
|
int rdv4_validate(rdv40_validation_t *mem) {
|
||||||
|
|
||||||
|
// Flash ID hash (sha1)
|
||||||
|
uint8_t sha_hash[20] = {0};
|
||||||
|
mbedtls_sha1(mem->flashid, sizeof(mem->flashid), sha_hash);
|
||||||
|
|
||||||
|
// set up RSA
|
||||||
|
mbedtls_rsa_context rsa;
|
||||||
|
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
||||||
|
rsa.len = RRG_RSA_KEY_LEN;
|
||||||
|
mbedtls_mpi_read_string(&rsa.N, 16, RRG_RSA_N);
|
||||||
|
mbedtls_mpi_read_string(&rsa.E, 16, RRG_RSA_E);
|
||||||
|
|
||||||
|
// Verify (public key)
|
||||||
|
int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, mem->signature);
|
||||||
|
mbedtls_rsa_free(&rsa);
|
||||||
|
|
||||||
|
if (is_verified == 0) {
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
return PM3_EFAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rdv4_sign_write(uint8_t *signature, uint8_t slen){
|
||||||
|
// save to mem
|
||||||
|
clearCommandBuffer();
|
||||||
|
PacketResponseNG resp;
|
||||||
|
SendCommandOLD(CMD_FLASHMEM_WRITE, FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0, signature, slen);
|
||||||
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
|
} else {
|
||||||
|
if (!resp.oldarg[0]) {
|
||||||
|
PrintAndLogEx(FAILED, "Writing signature ( "_RED_("fail") ")");
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(SUCCESS, "Writing signature ( "_GREEN_("ok") " ) at offset %u", FLASH_MEM_SIGNATURE_OFFSET);
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PM3_EFAILED;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdFlashmemSpiBaudrate(const char *Cmd) {
|
static int CmdFlashmemSpiBaudrate(const char *Cmd) {
|
||||||
|
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
|
@ -344,23 +461,14 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
// shall_write = arg_get_lit(ctx, 2);
|
// shall_write = arg_get_lit(ctx, 2);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
clearCommandBuffer();
|
// validate signature data
|
||||||
SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
|
|
||||||
PacketResponseNG resp;
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
|
||||||
return PM3_ETIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
|
||||||
if (isok == false) {
|
|
||||||
PrintAndLogEx(FAILED, "failed");
|
|
||||||
return PM3_EFLASH;
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate signature here
|
|
||||||
rdv40_validation_t mem;
|
rdv40_validation_t mem;
|
||||||
memcpy(&mem, (rdv40_validation_t *)resp.data.asBytes, sizeof(rdv40_validation_t));
|
int res = rdv4_get_signature(&mem);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = rdv4_validate(&mem);
|
||||||
|
|
||||||
// Flash ID hash (sha1)
|
// Flash ID hash (sha1)
|
||||||
uint8_t sha_hash[20] = {0};
|
uint8_t sha_hash[20] = {0};
|
||||||
|
@ -369,7 +477,6 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
// print header
|
// print header
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
|
PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
|
||||||
// PrintAndLogEx(INFO, "-----------------------------------------------------------------");
|
|
||||||
PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid)));
|
PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid)));
|
||||||
PrintAndLogEx(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
PrintAndLogEx(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
@ -378,69 +485,16 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32));
|
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------
|
|
||||||
// RRG Public RSA Key
|
|
||||||
//
|
|
||||||
|
|
||||||
// public key Exponent E
|
|
||||||
#define RSA_E "010001"
|
|
||||||
|
|
||||||
// public key modulus N
|
|
||||||
#define RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF" \
|
|
||||||
"4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F" \
|
|
||||||
"9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33" \
|
|
||||||
"DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------
|
|
||||||
// Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
|
|
||||||
//
|
|
||||||
|
|
||||||
// private key Exponent D
|
|
||||||
#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
|
|
||||||
"66CA472BC44D253102F8B4A9D3BFA750" \
|
|
||||||
"91386C0077937FE33FA3252D28855837" \
|
|
||||||
"AE1B484A8A9A45F7EE8C0C634F99E8CD" \
|
|
||||||
"DF79C5CE07EE72C7F123142198164234" \
|
|
||||||
"CABB724CF78B8173B9F880FC86322407" \
|
|
||||||
"AF1FEDFDDE2BEB674CA15F3E81A1521E" \
|
|
||||||
"071513A1E85B5DFA031F21ECAE91A34D"
|
|
||||||
|
|
||||||
// prime P
|
|
||||||
#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
|
|
||||||
"2C01CAD19EA484A87EA4377637E75500" \
|
|
||||||
"FCB2005C5C7DD6EC4AC023CDA285D796" \
|
|
||||||
"C3D9E75E1EFC42488BB4F1D13AC30A57"
|
|
||||||
|
|
||||||
// prime Q
|
|
||||||
#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
|
|
||||||
"E211C2B9E5DB1ED0BF61D0D9899620F4" \
|
|
||||||
"910E4168387E3C30AA1E00C339A79508" \
|
|
||||||
"8452DD96A9A5EA5D9DCA68DA636032AF"
|
|
||||||
|
|
||||||
#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
|
|
||||||
"3C94D22288ACD763FD8E5600ED4A702D" \
|
|
||||||
"F84198A5F06C2E72236AE490C93F07F8" \
|
|
||||||
"3CC559CD27BC2D1CA488811730BB5725"
|
|
||||||
|
|
||||||
#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
|
|
||||||
"D8AAEA56749EA28623272E4F7D0592AF" \
|
|
||||||
"7C1F1313CAC9471B5C523BFE592F517B" \
|
|
||||||
"407A1BD76C164B93DA2D32A383E58357"
|
|
||||||
|
|
||||||
#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
|
|
||||||
"F38D18D2B2F0E2DD275AA977E2BF4411" \
|
|
||||||
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
|
|
||||||
"A74206CEC169D74BF5A8C50D6F48EA08"
|
|
||||||
|
|
||||||
#define KEY_LEN 128
|
|
||||||
|
|
||||||
mbedtls_rsa_context rsa;
|
mbedtls_rsa_context rsa;
|
||||||
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
||||||
|
|
||||||
rsa.len = KEY_LEN;
|
rsa.len = RRG_RSA_KEY_LEN;
|
||||||
|
|
||||||
mbedtls_mpi_read_string(&rsa.N, 16, RSA_N);
|
// add public key
|
||||||
mbedtls_mpi_read_string(&rsa.E, 16, RSA_E);
|
mbedtls_mpi_read_string(&rsa.N, 16, RRG_RSA_N);
|
||||||
|
mbedtls_mpi_read_string(&rsa.E, 16, RRG_RSA_E);
|
||||||
|
|
||||||
|
// add private key
|
||||||
mbedtls_mpi_read_string(&rsa.D, 16, RSA_D);
|
mbedtls_mpi_read_string(&rsa.D, 16, RSA_D);
|
||||||
mbedtls_mpi_read_string(&rsa.P, 16, RSA_P);
|
mbedtls_mpi_read_string(&rsa.P, 16, RSA_P);
|
||||||
mbedtls_mpi_read_string(&rsa.Q, 16, RSA_Q);
|
mbedtls_mpi_read_string(&rsa.Q, 16, RSA_Q);
|
||||||
|
@ -448,8 +502,6 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
|
mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
|
||||||
mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
|
mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
|
||||||
|
|
||||||
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0);
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------");
|
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------");
|
||||||
|
|
||||||
|
@ -466,48 +518,35 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, " %.64s", str_pk + 64);
|
PrintAndLogEx(INFO, " %.64s", str_pk + 64);
|
||||||
PrintAndLogEx(INFO, " %.64s", str_pk + 128);
|
PrintAndLogEx(INFO, " %.64s", str_pk + 128);
|
||||||
PrintAndLogEx(INFO, " %.64s", str_pk + 192);
|
PrintAndLogEx(INFO, " %.64s", str_pk + 192);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
const char *msgkey = "RSA key validation... ";
|
|
||||||
if (is_keyok)
|
|
||||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgkey);
|
|
||||||
else
|
|
||||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgkey);
|
|
||||||
|
|
||||||
//
|
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0);
|
||||||
uint8_t from_device[KEY_LEN];
|
PrintAndLogEx(
|
||||||
uint8_t sign[KEY_LEN];
|
(is_keyok) ? SUCCESS : FAILED,
|
||||||
|
"RSA key validation... ( %s )",
|
||||||
|
(is_keyok) ? _GREEN_("ok") : _RED_("fail")
|
||||||
|
);
|
||||||
|
|
||||||
// to be verified
|
// to be verified
|
||||||
memcpy(from_device, mem.signature, KEY_LEN);
|
uint8_t from_device[RRG_RSA_KEY_LEN];
|
||||||
|
memcpy(from_device, mem.signature, RRG_RSA_KEY_LEN);
|
||||||
|
|
||||||
// to be signed (all zeros
|
// to be signed
|
||||||
memset(sign, 0, KEY_LEN);
|
uint8_t sign[RRG_RSA_KEY_LEN];
|
||||||
|
memset(sign, 0, RRG_RSA_KEY_LEN);
|
||||||
|
|
||||||
// Signing (private key)
|
// Signing (private key)
|
||||||
if (shall_sign) {
|
if (shall_sign) {
|
||||||
|
|
||||||
int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
|
int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
|
||||||
const char *msgsign = "RSA signing.......... ";
|
PrintAndLogEx(
|
||||||
if (is_signed == 0)
|
(is_signed == 0) ? SUCCESS : FAILED,
|
||||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgsign);
|
"RSA signing.......... ( %s )",
|
||||||
else
|
(is_signed == 0) ? _GREEN_("ok") : _RED_("fail")
|
||||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgsign);
|
);
|
||||||
|
|
||||||
if (shall_write) {
|
if (shall_write) {
|
||||||
// save to mem
|
rdv4_sign_write(sign, RRG_RSA_KEY_LEN);
|
||||||
clearCommandBuffer();
|
|
||||||
SendCommandOLD(CMD_FLASHMEM_WRITE, FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0, sign, sizeof(sign));
|
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (!resp.oldarg[0])
|
|
||||||
PrintAndLogEx(FAILED, "Writing signature failed");
|
|
||||||
else
|
|
||||||
PrintAndLogEx(SUCCESS, "Writing signature ok [offset: %u]", FLASH_MEM_SIGNATURE_OFFSET);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PrintAndLogEx(INFO, "Signed");
|
PrintAndLogEx(INFO, "Signed");
|
||||||
for (int i = 0; i < (sizeof(sign) / 32); i++) {
|
for (int i = 0; i < (sizeof(sign) / 32); i++) {
|
||||||
|
@ -517,14 +556,15 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
|
|
||||||
// Verify (public key)
|
// Verify (public key)
|
||||||
int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device);
|
int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device);
|
||||||
const char *msgverify = "RSA verification..... ";
|
mbedtls_rsa_free(&rsa);
|
||||||
if (is_verified == 0)
|
|
||||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgverify);
|
PrintAndLogEx(
|
||||||
else
|
(is_verified == 0) ? SUCCESS : FAILED,
|
||||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgverify);
|
"RSA verification..... ( %s )",
|
||||||
|
(is_verified == 0) ? _GREEN_("ok") : _RED_("fail")
|
||||||
|
);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
mbedtls_rsa_free(&rsa);
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#define CMDFLASHMEM_H__
|
#define CMDFLASHMEM_H__
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "pmflash.h" // rdv40validation_t
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DICTIONARY_NONE = 0,
|
DICTIONARY_NONE = 0,
|
||||||
|
@ -21,5 +22,6 @@ typedef enum {
|
||||||
} Dictionary_t;
|
} Dictionary_t;
|
||||||
|
|
||||||
int CmdFlashMem(const char *Cmd);
|
int CmdFlashMem(const char *Cmd);
|
||||||
|
int rdv4_get_signature(rdv40_validation_t *out);
|
||||||
|
int rdv4_validate(rdv40_validation_t *mem);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "cmdhf.h"
|
#include "cmdhf.h"
|
||||||
|
|
||||||
#include <ctype.h> // tolower
|
#include <ctype.h> // tolower
|
||||||
|
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "cliparser.h" // parse
|
#include "cliparser.h" // parse
|
||||||
#include "comms.h" // clearCommandBuffer
|
#include "comms.h" // clearCommandBuffer
|
||||||
|
@ -23,8 +22,10 @@
|
||||||
#include "cmdhf14b.h" // ISO14443-B
|
#include "cmdhf14b.h" // ISO14443-B
|
||||||
#include "cmdhf15.h" // ISO15693
|
#include "cmdhf15.h" // ISO15693
|
||||||
#include "cmdhfepa.h"
|
#include "cmdhfepa.h"
|
||||||
|
#include "cmdhfemrtd.h" // eMRTD
|
||||||
#include "cmdhflegic.h" // LEGIC
|
#include "cmdhflegic.h" // LEGIC
|
||||||
#include "cmdhficlass.h" // ICLASS
|
#include "cmdhficlass.h" // ICLASS
|
||||||
|
#include "cmdhfjooki.h" // MFU based Jooki
|
||||||
#include "cmdhfmf.h" // CLASSIC
|
#include "cmdhfmf.h" // CLASSIC
|
||||||
#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc
|
#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc
|
||||||
#include "cmdhfmfp.h" // Mifare Plus
|
#include "cmdhfmfp.h" // Mifare Plus
|
||||||
|
@ -46,50 +47,20 @@
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_hf_search(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf search");
|
|
||||||
PrintAndLogEx(NORMAL, "Will try to find a HF read out of the unknown tag.");
|
|
||||||
PrintAndLogEx(NORMAL, "Continues to search for all different HF protocols");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - This help");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int usage_hf_sniff(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "The high frequency sniffer will assign all available memory on device for sniffed data");
|
|
||||||
PrintAndLogEx(NORMAL, "Use " _YELLOW_("'data samples'")" command to download from device, and " _YELLOW_("'data plot'")" to look at it");
|
|
||||||
PrintAndLogEx(NORMAL, "Press button to quit the sniffing.\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf sniff <skip pairs> <skip triggers>");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - This help");
|
|
||||||
PrintAndLogEx(NORMAL, " <skip pairs> - skip sample pairs");
|
|
||||||
PrintAndLogEx(NORMAL, " <skip triggers> - skip number of triggers");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf sniff"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf sniff 1000 0"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int usage_hf_tune(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Continuously measure HF antenna tuning.");
|
|
||||||
PrintAndLogEx(NORMAL, "Press button or `enter` to interrupt.");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf tune [h] [<iter>]");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - This help");
|
|
||||||
PrintAndLogEx(NORMAL, " <iter> - number of iterations (default: 0=infinite)");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf tune 1"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CmdHFSearch(const char *Cmd) {
|
int CmdHFSearch(const char *Cmd) {
|
||||||
|
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
CLIParserContext *ctx;
|
||||||
if (cmdp == 'h') return usage_hf_search();
|
CLIParserInit(&ctx, "hf search",
|
||||||
|
"Will try to find a HF read out of the unknown tag.\n"
|
||||||
|
"Continues to search for all different HF protocols.",
|
||||||
|
"hf search"
|
||||||
|
);
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
int res = PM3_ESOFT;
|
int res = PM3_ESOFT;
|
||||||
|
|
||||||
|
@ -141,7 +112,7 @@ int CmdHFSearch(const char *Cmd) {
|
||||||
PROMPT_CLEARLINE;
|
PROMPT_CLEARLINE;
|
||||||
PrintAndLogEx(INPLACE, " Searching for LEGIC tag...");
|
PrintAndLogEx(INPLACE, " Searching for LEGIC tag...");
|
||||||
if (IfPm3Legicrf()) {
|
if (IfPm3Legicrf()) {
|
||||||
if (readLegicUid(false) == PM3_SUCCESS) {
|
if (readLegicUid(false, false) == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC Prime tag") " found\n");
|
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC Prime tag") " found\n");
|
||||||
res = PM3_SUCCESS;
|
res = PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -189,18 +160,51 @@ int CmdHFSearch(const char *Cmd) {
|
||||||
|
|
||||||
PROMPT_CLEARLINE;
|
PROMPT_CLEARLINE;
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
|
|
||||||
PrintAndLogEx(WARNING, _RED_("No known/supported 13.56 MHz tags found"));
|
PrintAndLogEx(WARNING, _RED_("No known/supported 13.56 MHz tags found"));
|
||||||
res = PM3_ESOFT;
|
res = PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DropField();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHFTune(const char *Cmd) {
|
int CmdHFTune(const char *Cmd) {
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
|
||||||
if (cmdp == 'h') return usage_hf_tune();
|
CLIParserContext *ctx;
|
||||||
int iter = param_get32ex(Cmd, 0, 0, 10);
|
CLIParserInit(&ctx, "hf tune",
|
||||||
|
"Continuously measure HF antenna tuning.\n"
|
||||||
|
"Press button or <Enter> to interrupt.",
|
||||||
|
"hf tune\n"
|
||||||
|
"hf tune --mix"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_u64_0("n", "iter", "<dec>", "number of iterations (default: 0=infinite)"),
|
||||||
|
arg_lit0(NULL, "bar", "bar style"),
|
||||||
|
arg_lit0(NULL, "mix", "mixed style"),
|
||||||
|
arg_lit0(NULL, "value", "values style"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
uint32_t iter = arg_get_u32_def(ctx, 1, 0);
|
||||||
|
bool is_bar = arg_get_lit(ctx, 2);
|
||||||
|
bool is_mix = arg_get_lit(ctx, 3);
|
||||||
|
bool is_value = arg_get_lit(ctx, 4);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if ((is_bar + is_mix + is_value) > 1) {
|
||||||
|
PrintAndLogEx(ERR, "Select only one output style");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
barMode_t style = session.bar_mode;
|
||||||
|
if (is_bar)
|
||||||
|
style = STYLE_BAR;
|
||||||
|
if (is_mix)
|
||||||
|
style = STYLE_MIXED;
|
||||||
|
if (is_value)
|
||||||
|
style = STYLE_VALUE;
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Measuring HF antenna, click " _GREEN_("pm3 button") " or press " _GREEN_("Enter") " to exit");
|
PrintAndLogEx(INFO, "Measuring HF antenna, click " _GREEN_("pm3 button") " or press " _GREEN_("Enter") " to exit");
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
@ -214,6 +218,12 @@ int CmdHFTune(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mode[0] = 2;
|
mode[0] = 2;
|
||||||
|
|
||||||
|
uint32_t max = 0xFFFF;
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
print_progress(0, max, style);
|
||||||
|
|
||||||
// loop forever (till button pressed) if iter = 0 (default)
|
// loop forever (till button pressed) if iter = 0 (default)
|
||||||
for (uint8_t i = 0; iter == 0 || i < iter; i++) {
|
for (uint8_t i = 0; iter == 0 || i < iter; i++) {
|
||||||
if (kbd_enter_pressed()) {
|
if (kbd_enter_pressed()) {
|
||||||
|
@ -224,15 +234,23 @@ int CmdHFTune(const char *Cmd) {
|
||||||
if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_HF, &resp, 1000)) {
|
if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_HF, &resp, 1000)) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark HF measure, aborting");
|
PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark HF measure, aborting");
|
||||||
return PM3_ETIMEOUT;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((resp.status == PM3_EOPABORTED) || (resp.length != sizeof(uint16_t))) {
|
if ((resp.status == PM3_EOPABORTED) || (resp.length != sizeof(uint16_t))) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t volt = resp.data.asDwords[0] & 0xFFFF;
|
uint16_t volt = resp.data.asDwords[0] & 0xFFFF;
|
||||||
PrintAndLogEx(INPLACE, " %u mV / %2u V", volt, (uint16_t)(volt / 1000));
|
if (first) {
|
||||||
|
max = (volt * 1.03);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
if (volt > max) {
|
||||||
|
max = (volt * 1.03);
|
||||||
|
}
|
||||||
|
print_progress(volt, max, style);
|
||||||
}
|
}
|
||||||
mode[0] = 3;
|
mode[0] = 3;
|
||||||
|
|
||||||
|
@ -241,7 +259,7 @@ int CmdHFTune(const char *Cmd) {
|
||||||
PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark HF shutdown, aborting");
|
PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark HF shutdown, aborting");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "\x1b%c[2K\r", 30);
|
||||||
PrintAndLogEx(INFO, "Done.");
|
PrintAndLogEx(INFO, "Done.");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -251,16 +269,31 @@ int CmdHFTune(const char *Cmd) {
|
||||||
// Takes all available bigbuff memory
|
// Takes all available bigbuff memory
|
||||||
// data sample to download? Not sure what we can do with the data.
|
// data sample to download? Not sure what we can do with the data.
|
||||||
int CmdHFSniff(const char *Cmd) {
|
int CmdHFSniff(const char *Cmd) {
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
|
||||||
if (cmdp == 'h') return usage_hf_sniff();
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf sniff",
|
||||||
|
"The high frequency sniffer will assign all available memory on device for sniffed data.\n"
|
||||||
|
"Use `data samples` to download from device and `data plot` to visualize it.\n"
|
||||||
|
"Press button to quit the sniffing.",
|
||||||
|
"hf sniff\n"
|
||||||
|
"hf sniff --sp 1000 --st 0 -> skip 1000 pairs, skip 0 triggers"
|
||||||
|
);
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_u64_0(NULL, "sp", "<dec>", "skip sample pairs"),
|
||||||
|
arg_u64_0(NULL, "st", "<dec>", "skip number of triggers"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint32_t samplesToSkip;
|
uint32_t samplesToSkip;
|
||||||
uint32_t triggersToSkip;
|
uint32_t triggersToSkip;
|
||||||
} PACKED params;
|
} PACKED params;
|
||||||
|
|
||||||
params.samplesToSkip = param_get32ex(Cmd, 0, 0, 10);
|
params.samplesToSkip = arg_get_u32_def(ctx, 1, 0);
|
||||||
params.triggersToSkip = param_get32ex(Cmd, 1, 0, 10);
|
params.triggersToSkip = arg_get_u32_def(ctx, 2, 0);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_SNIFF, (uint8_t *)¶ms, sizeof(params));
|
SendCommandNG(CMD_HF_SNIFF, (uint8_t *)¶ms, sizeof(params));
|
||||||
|
@ -362,8 +395,10 @@ static command_t CommandTable[] = {
|
||||||
{"15", CmdHF15, AlwaysAvailable, "{ ISO15693 RFIDs... }"},
|
{"15", CmdHF15, AlwaysAvailable, "{ ISO15693 RFIDs... }"},
|
||||||
// {"cryptorf", CmdHFCryptoRF, AlwaysAvailable, "{ CryptoRF RFIDs... }"},
|
// {"cryptorf", CmdHFCryptoRF, AlwaysAvailable, "{ CryptoRF RFIDs... }"},
|
||||||
{"epa", CmdHFEPA, AlwaysAvailable, "{ German Identification Card... }"},
|
{"epa", CmdHFEPA, AlwaysAvailable, "{ German Identification Card... }"},
|
||||||
|
{"emrtd", CmdHFeMRTD, AlwaysAvailable, "{ Machine Readable Travel Document... }"},
|
||||||
{"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / FeliCa RFIDs... }"},
|
{"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / FeliCa RFIDs... }"},
|
||||||
{"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"},
|
{"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"},
|
||||||
|
{"jooki", CmdHF_Jooki, AlwaysAvailable, "{ Jooki RFIDs... }"},
|
||||||
{"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"},
|
{"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"},
|
||||||
{"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"},
|
{"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"},
|
||||||
{"lto", CmdHFLTO, AlwaysAvailable, "{ LTO Cartridge Memory RFIDs... }"},
|
{"lto", CmdHFLTO, AlwaysAvailable, "{ LTO Cartridge Memory RFIDs... }"},
|
||||||
|
@ -381,7 +416,7 @@ static command_t CommandTable[] = {
|
||||||
{"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"},
|
{"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"},
|
||||||
{"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"},
|
{"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"},
|
||||||
{"search", CmdHFSearch, AlwaysAvailable, "Search for known HF tags"},
|
{"search", CmdHFSearch, AlwaysAvailable, "Search for known HF tags"},
|
||||||
{"sniff", CmdHFSniff, IfPm3Hfsniff, "<samples to skip (10000)> <triggers to skip (1)> Generic HF Sniff"},
|
{"sniff", CmdHFSniff, IfPm3Hfsniff, "Generic HF Sniff"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,7 +27,7 @@ int CmdHF14ASniff(const char *Cmd); // used by hf topaz sniff
|
||||||
int CmdHF14ASim(const char *Cmd); // used by hf mfu sim
|
int CmdHF14ASim(const char *Cmd); // used by hf mfu sim
|
||||||
|
|
||||||
int hf14a_getconfig(hf14a_config *config);
|
int hf14a_getconfig(hf14a_config *config);
|
||||||
int hf14a_setconfig(hf14a_config *config);
|
int hf14a_setconfig(hf14a_config *config, bool verbose);
|
||||||
int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search);
|
int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search);
|
||||||
const char *getTagInfo(uint8_t uid);
|
const char *getTagInfo(uint8_t uid);
|
||||||
int Hf14443_4aGetCardData(iso14a_card_select_t *card);
|
int Hf14443_4aGetCardData(iso14a_card_select_t *card);
|
||||||
|
|
|
@ -24,8 +24,11 @@
|
||||||
#include "protocols.h" // definitions of ISO14B/7816 protocol
|
#include "protocols.h" // definitions of ISO14B/7816 protocol
|
||||||
#include "emv/apduinfo.h" // GetAPDUCodeDescription
|
#include "emv/apduinfo.h" // GetAPDUCodeDescription
|
||||||
#include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint
|
#include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint
|
||||||
|
#include "aidsearch.h"
|
||||||
|
|
||||||
|
#define MAX_14B_TIMEOUT 40542464U // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
|
||||||
#define TIMEOUT 2000
|
#define TIMEOUT 2000
|
||||||
|
#define APDU_TIMEOUT 2000
|
||||||
|
|
||||||
// iso14b apdu input frame length
|
// iso14b apdu input frame length
|
||||||
static uint16_t apdu_frame_length = 0;
|
static uint16_t apdu_frame_length = 0;
|
||||||
|
@ -34,21 +37,6 @@ bool apdu_in_framing_enable = true;
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_hf_14b_write_srx(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf 14b [h] sriwrite <1|2> <block> <data>");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h this help");
|
|
||||||
PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512");
|
|
||||||
PrintAndLogEx(NORMAL, " <block> (hex) block number depends on tag, special block == FF");
|
|
||||||
PrintAndLogEx(NORMAL, " <data> hex bytes of data to be written");
|
|
||||||
PrintAndLogEx(NORMAL, "Example:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sriwrite 1 7F 11223344"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sriwrite 1 FF 11223344"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sriwrite 2 15 11223344"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sriwrite 2 FF 11223344"));
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int switch_off_field_14b(void) {
|
static int switch_off_field_14b(void) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||||
|
@ -63,6 +51,103 @@ static uint16_t get_sw(uint8_t *d, uint8_t n) {
|
||||||
return d[n] * 0x0100 + d[n + 1];
|
return d[n] * 0x0100 + d[n + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hf14b_aid_search(bool verbose) {
|
||||||
|
|
||||||
|
int elmindx = 0;
|
||||||
|
json_t *root = AIDSearchInit(verbose);
|
||||||
|
if (root == NULL) {
|
||||||
|
switch_off_field_14b();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "-------------------- " _CYAN_("AID Search") " --------------------");
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
bool leave_signal_on = true;
|
||||||
|
bool activate_field = true;
|
||||||
|
for (elmindx = 0; elmindx < json_array_size(root); elmindx++) {
|
||||||
|
|
||||||
|
if (kbd_enter_pressed()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_t *data = AIDSearchGetElm(root, elmindx);
|
||||||
|
uint8_t vaid[200] = {0};
|
||||||
|
int vaidlen = 0;
|
||||||
|
if (!AIDGetFromElm(data, vaid, sizeof(vaid), &vaidlen) || !vaidlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
// COMPUTE APDU
|
||||||
|
uint8_t apdu_data[PM3_CMD_DATA_SIZE] = {0};
|
||||||
|
int apdu_len = 0;
|
||||||
|
sAPDU apdu = (sAPDU) {0x00, 0xa4, 0x04, 0x00, vaidlen, vaid};
|
||||||
|
|
||||||
|
if (APDUEncodeS(&apdu, false, 0x00, apdu_data, &apdu_len)) {
|
||||||
|
PrintAndLogEx(ERR, "APDU encoding error.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(DEBUG, ">>>> %s", sprint_hex(apdu_data, apdu_len));
|
||||||
|
|
||||||
|
int resultlen = 0;
|
||||||
|
uint8_t result[1024] = {0};
|
||||||
|
int res = exchange_14b_apdu(apdu_data, apdu_len, activate_field, leave_signal_on, result, sizeof(result), &resultlen, -1);
|
||||||
|
activate_field = false;
|
||||||
|
if (res)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint16_t sw = get_sw(result, resultlen);
|
||||||
|
|
||||||
|
uint8_t dfname[200] = {0};
|
||||||
|
size_t dfnamelen = 0;
|
||||||
|
if (resultlen > 3) {
|
||||||
|
struct tlvdb *tlv = tlvdb_parse_multi(result, resultlen);
|
||||||
|
if (tlv) {
|
||||||
|
// 0x84 Dedicated File (DF) Name
|
||||||
|
const struct tlv *dfnametlv = tlvdb_get_tlv(tlvdb_find_full(tlv, 0x84));
|
||||||
|
if (dfnametlv) {
|
||||||
|
dfnamelen = dfnametlv->len;
|
||||||
|
memcpy(dfname, dfnametlv->value, dfnamelen);
|
||||||
|
}
|
||||||
|
tlvdb_free(tlv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sw == 0x9000 || sw == 0x6283 || sw == 0x6285) {
|
||||||
|
if (sw == 0x9000) {
|
||||||
|
if (verbose) PrintAndLogEx(SUCCESS, "Application ( " _GREEN_("ok") " )");
|
||||||
|
} else {
|
||||||
|
if (verbose) PrintAndLogEx(WARNING, "Application ( " _RED_("blocked") " )");
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAIDDescriptionBuf(root, vaid, vaidlen, verbose);
|
||||||
|
|
||||||
|
if (dfnamelen) {
|
||||||
|
if (dfnamelen == vaidlen) {
|
||||||
|
if (memcmp(dfname, vaid, vaidlen) == 0) {
|
||||||
|
if (verbose) PrintAndLogEx(INFO, "(DF) Name found and equal to AID");
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(INFO, "(DF) Name not equal to AID: %s :", sprint_hex(dfname, dfnamelen));
|
||||||
|
PrintAIDDescriptionBuf(root, dfname, dfnamelen, verbose);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(INFO, "(DF) Name not equal to AID: %s :", sprint_hex(dfname, dfnamelen));
|
||||||
|
PrintAIDDescriptionBuf(root, dfname, dfnamelen, verbose);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (verbose) PrintAndLogEx(INFO, "(DF) Name not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) PrintAndLogEx(SUCCESS, "----------------------------------------------------");
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch_off_field_14b();
|
||||||
|
if (verbose == false && found)
|
||||||
|
PrintAndLogEx(INFO, "----------------------------------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
static bool wait_cmd_14b(bool verbose, bool is_select) {
|
static bool wait_cmd_14b(bool verbose, bool is_select) {
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
@ -102,7 +187,6 @@ static bool wait_cmd_14b(bool verbose, bool is_select) {
|
||||||
(crc) ? _GREEN_("ok") : _RED_("fail")
|
(crc) ? _GREEN_("ok") : _RED_("fail")
|
||||||
);
|
);
|
||||||
} else if (len == 0) {
|
} else if (len == 0) {
|
||||||
if (verbose)
|
|
||||||
PrintAndLogEx(INFO, "no response from tag");
|
PrintAndLogEx(INFO, "no response from tag");
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
|
PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
|
||||||
|
@ -187,7 +271,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
|
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf 14b raw",
|
CLIParserInit(&ctx, "hf 14b raw",
|
||||||
"Sends raw bytes to card ",
|
"Sends raw bytes to card",
|
||||||
"hf 14b raw -cks --data 0200a40400 -> standard select\n"
|
"hf 14b raw -cks --data 0200a40400 -> standard select\n"
|
||||||
"hf 14b raw -ck --sr --data 0200a40400 -> SRx select\n"
|
"hf 14b raw -ck --sr --data 0200a40400 -> SRx select\n"
|
||||||
"hf 14b raw -ck --cts --data 0200a40400 -> C-ticket select\n"
|
"hf 14b raw -ck --cts --data 0200a40400 -> C-ticket select\n"
|
||||||
|
@ -200,7 +284,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
arg_lit0(NULL, "sr", "activate field, use SRx ST select"),
|
arg_lit0(NULL, "sr", "activate field, use SRx ST select"),
|
||||||
arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"),
|
arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"),
|
||||||
arg_lit0("c", "crc", "calculate and append CRC"),
|
arg_lit0("c", "crc", "calculate and append CRC"),
|
||||||
arg_lit0("r", "noresponse", "do not read response from card"),
|
arg_lit0(NULL, "noresponse", "do not read response from card"),
|
||||||
arg_int0("t", "timeout", "<dec>", "timeout in ms"),
|
arg_int0("t", "timeout", "<dec>", "timeout in ms"),
|
||||||
arg_lit0("v", "verbose", "verbose"),
|
arg_lit0("v", "verbose", "verbose"),
|
||||||
arg_strx0("d", "data", "<hex>", "data, bytes to send"),
|
arg_strx0("d", "data", "<hex>", "data, bytes to send"),
|
||||||
|
@ -244,18 +328,20 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
}
|
}
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
|
||||||
uint32_t time_wait = 0;
|
uint32_t time_wait = 0;
|
||||||
if (user_timeout > 0) {
|
if (user_timeout > 0) {
|
||||||
|
|
||||||
#define MAX_14B_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
|
|
||||||
flags |= ISO14B_SET_TIMEOUT;
|
flags |= ISO14B_SET_TIMEOUT;
|
||||||
if (user_timeout > MAX_14B_TIMEOUT) {
|
|
||||||
user_timeout = MAX_14B_TIMEOUT;
|
uint32_t max_timeout = user_timeout;
|
||||||
|
if (max_timeout > MAX_14B_TIMEOUT) {
|
||||||
|
max_timeout = MAX_14B_TIMEOUT;
|
||||||
PrintAndLogEx(INFO, "set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
|
PrintAndLogEx(INFO, "set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
|
||||||
}
|
}
|
||||||
time_wait = 13560000 / 1000 / (8 * 16) * user_timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
|
time_wait = ((13560000 / 1000 / (8 * 16)) * max_timeout); // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "using timeout %u", user_timeout);
|
PrintAndLogEx(INFO, "using timeout %u", max_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keep_field_on == 0)
|
if (keep_field_on == 0)
|
||||||
|
@ -308,8 +394,7 @@ static bool get_14b_UID(iso14b_card_select_t *card) {
|
||||||
if (card == NULL)
|
if (card == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int status = 0;
|
int status;
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||||
|
@ -628,12 +713,12 @@ static void print_ct_general_info(void *vcard) {
|
||||||
memcpy(&card, (iso14b_cts_card_select_t *)vcard, sizeof(iso14b_cts_card_select_t));
|
memcpy(&card, (iso14b_cts_card_select_t *)vcard, sizeof(iso14b_cts_card_select_t));
|
||||||
|
|
||||||
uint32_t uid32 = (card.uid[0] | card.uid[1] << 8 | card.uid[2] << 16 | card.uid[3] << 24);
|
uint32_t uid32 = (card.uid[0] | card.uid[1] << 8 | card.uid[2] << 16 | card.uid[3] << 24);
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(SUCCESS, "ASK C-Ticket");
|
PrintAndLogEx(SUCCESS, "ASK C-Ticket");
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s") " ( " _YELLOW_("%010u") " )", sprint_hex(card.uid, sizeof(card.uid)), uid32);
|
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s") " ( " _YELLOW_("%010u") " )", sprint_hex(card.uid, sizeof(card.uid)), uid32);
|
||||||
PrintAndLogEx(SUCCESS, " Product Code: %02X", card.pc);
|
PrintAndLogEx(SUCCESS, " Product Code: %02X", card.pc);
|
||||||
PrintAndLogEx(SUCCESS, " Facility Code: %02X", card.fc);
|
PrintAndLogEx(SUCCESS, " Facility Code: %02X", card.fc);
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// iceman, calypso?
|
// iceman, calypso?
|
||||||
|
@ -649,7 +734,7 @@ static void print_ct_general_info(void *vcard) {
|
||||||
// 0200a4040010a000000018300301000000000000000000 (resp 02 6a 82 [4b 4c])
|
// 0200a4040010a000000018300301000000000000000000 (resp 02 6a 82 [4b 4c])
|
||||||
|
|
||||||
// 14b get and print Full Info (as much as we know)
|
// 14b get and print Full Info (as much as we know)
|
||||||
static bool HF14B_Std_Info(bool verbose) {
|
static bool HF14B_Std_Info(bool verbose, bool do_aid_search) {
|
||||||
|
|
||||||
bool is_success = false;
|
bool is_success = false;
|
||||||
|
|
||||||
|
@ -670,14 +755,21 @@ static bool HF14B_Std_Info(bool verbose) {
|
||||||
int status = resp.oldarg[0];
|
int status = resp.oldarg[0];
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 0:
|
case 0: {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "-------------------- " _CYAN_("Tag information") " --------------------");
|
||||||
PrintAndLogEx(SUCCESS, " UID : " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
PrintAndLogEx(SUCCESS, " UID : " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||||
PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb)));
|
PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb)));
|
||||||
PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid);
|
PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid);
|
||||||
print_atqb_resp(card.atqb, card.cid);
|
print_atqb_resp(card.atqb, card.cid);
|
||||||
|
|
||||||
|
if (do_aid_search) {
|
||||||
|
hf14b_aid_search(verbose);
|
||||||
|
}
|
||||||
|
|
||||||
is_success = true;
|
is_success = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case -1:
|
case -1:
|
||||||
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail");
|
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail");
|
||||||
break;
|
break;
|
||||||
|
@ -693,7 +785,7 @@ static bool HF14B_Std_Info(bool verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SRx get and print full info (needs more info...)
|
// SRx get and print full info (needs more info...)
|
||||||
static bool HF14B_ST_Info(bool verbose) {
|
static bool HF14B_ST_Info(bool verbose, bool do_aid_search) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0);
|
||||||
|
@ -711,6 +803,10 @@ static bool HF14B_ST_Info(bool verbose) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
print_st_general_info(card.uid, card.uidlen);
|
print_st_general_info(card.uid, card.uidlen);
|
||||||
|
|
||||||
|
if (do_aid_search) {
|
||||||
|
hf14b_aid_search(verbose);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,13 +820,15 @@ static int CmdHF14Binfo(const char *Cmd) {
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
arg_lit0("s", "aidsearch", "checks if AIDs from aidlist.json is present on the card and prints information about found AIDs"),
|
||||||
arg_lit0("v", "verbose", "verbose"),
|
arg_lit0("v", "verbose", "verbose"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
bool verbose = arg_get_lit(ctx, 1);
|
bool do_aid_search = arg_get_lit(ctx, 1);
|
||||||
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return infoHF14B(verbose);
|
return infoHF14B(verbose, do_aid_search);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool HF14B_st_reader(bool verbose) {
|
static bool HF14B_st_reader(bool verbose) {
|
||||||
|
@ -1025,56 +1123,78 @@ static int CmdHF14BWriteSri(const char *Cmd) {
|
||||||
* Special block FF = otp_lock_reg block.
|
* Special block FF = otp_lock_reg block.
|
||||||
* Data len 4 bytes-
|
* Data len 4 bytes-
|
||||||
*/
|
*/
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
|
||||||
uint8_t blockno = -1;
|
|
||||||
uint8_t data[4] = {0x00};
|
|
||||||
bool isSrix4k = true;
|
|
||||||
char str[30];
|
|
||||||
memset(str, 0x00, sizeof(str));
|
|
||||||
|
|
||||||
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_write_srx();
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf 14b sriwrite",
|
||||||
|
"Write data to a SRI512 | SRIX4K block",
|
||||||
|
"hf 14b sriwrite --4k -b 100 -d 11223344\n"
|
||||||
|
"hf 14b sriwrite --4k --sb -d 11223344 --> special block write\n"
|
||||||
|
"hf 14b sriwrite --512 -b 15 -d 11223344\n"
|
||||||
|
"hf 14b sriwrite --512 --sb -d 11223344 --> special block write\n"
|
||||||
|
);
|
||||||
|
|
||||||
if (cmdp == '2')
|
void *argtable[] = {
|
||||||
isSrix4k = false;
|
arg_param_begin,
|
||||||
|
arg_int0("b", "block", "<dec>", "block number"),
|
||||||
//blockno = param_get8(Cmd, 1);
|
arg_str1("d", "data", "<hex>", "4 hex bytes"),
|
||||||
|
arg_lit0(NULL, "512", "target SRI 512 tag"),
|
||||||
if (param_gethex(Cmd, 1, &blockno, 2)) {
|
arg_lit0(NULL, "4k", "target SRIX 4k tag"),
|
||||||
PrintAndLogEx(WARNING, "block number must include 2 HEX symbols");
|
arg_lit0(NULL, "sb", "special block write at end of memory (0xFF)"),
|
||||||
return 0;
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
int blockno = arg_get_int_def(ctx, 1, -1);
|
||||||
|
int dlen = 0;
|
||||||
|
uint8_t data[4] = {0,0,0,0};
|
||||||
|
int res = CLIParamHexToBuf(arg_get_str(ctx, 2), data, sizeof(data), &dlen);
|
||||||
|
if (res) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSrix4k) {
|
bool use_sri512 = arg_get_lit(ctx, 3);
|
||||||
if (blockno > 0x7f && blockno != 0xff) {
|
bool use_srix4k = arg_get_lit(ctx, 4);
|
||||||
PrintAndLogEx(FAILED, "block number out of range");
|
bool special = arg_get_lit(ctx, 5);
|
||||||
return PM3_ESOFT;
|
CLIParserFree(ctx);
|
||||||
}
|
|
||||||
} else {
|
if (dlen != sizeof(data)) {
|
||||||
if (blockno > 0x0f && blockno != 0xff) {
|
PrintAndLogEx(FAILED, "data must be 4 hex bytes, got %d", dlen);
|
||||||
PrintAndLogEx(FAILED, "block number out of range");
|
return PM3_EINVARG;
|
||||||
return PM3_ESOFT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param_gethex(Cmd, 2, data, 8)) {
|
if (use_sri512 + use_srix4k > 1) {
|
||||||
PrintAndLogEx(WARNING, "data must include 8 HEX symbols");
|
PrintAndLogEx(FAILED, "Select only one card type");
|
||||||
return PM3_ESOFT;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockno == 0xff) {
|
if (use_srix4k && blockno > 0x7F) {
|
||||||
|
PrintAndLogEx(FAILED, "block number out of range, max 127 (0x7F)");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_sri512 && blockno > 0x0F) {
|
||||||
|
PrintAndLogEx(FAILED, "block number out of range, max 15 (0x0F)");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// special block at end of memory
|
||||||
|
if (special) {
|
||||||
|
blockno = 0xFF;
|
||||||
PrintAndLogEx(SUCCESS, "[%s] Write special block %02X [ " _YELLOW_("%s")" ]",
|
PrintAndLogEx(SUCCESS, "[%s] Write special block %02X [ " _YELLOW_("%s")" ]",
|
||||||
(isSrix4k) ? "SRIX4K" : "SRI512",
|
(use_srix4k) ? "SRIX4K" : "SRI512",
|
||||||
blockno,
|
blockno,
|
||||||
sprint_hex(data, 4)
|
sprint_hex(data, sizeof(data))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(SUCCESS, "[%s] Write block %02X [ " _YELLOW_("%s")" ]",
|
PrintAndLogEx(SUCCESS, "[%s] Write block %02X [ " _YELLOW_("%s")" ]",
|
||||||
(isSrix4k) ? "SRIX4K" : "SRI512",
|
(use_srix4k) ? "SRIX4K" : "SRI512",
|
||||||
blockno,
|
blockno,
|
||||||
sprint_hex(data, 4)
|
sprint_hex(data, sizeof(data))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char str[36];
|
||||||
|
memset(str, 0x00, sizeof(str));
|
||||||
sprintf(str, "--sr -c --data %02x%02x%02x%02x%02x%02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]);
|
sprintf(str, "--sr -c --data %02x%02x%02x%02x%02x%02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]);
|
||||||
return CmdHF14BCmdRaw(str);
|
return CmdHF14BCmdRaw(str);
|
||||||
}
|
}
|
||||||
|
@ -1414,7 +1534,7 @@ static int select_card_14443b_4(bool disconnect, iso14b_card_select_t *card) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) {
|
static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout, int user_timeout) {
|
||||||
*chainingout = false;
|
*chainingout = false;
|
||||||
|
|
||||||
if (activateField) {
|
if (activateField) {
|
||||||
|
@ -1429,16 +1549,27 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, bool
|
||||||
if (chainingin)
|
if (chainingin)
|
||||||
flags = ISO14B_SEND_CHAINING;
|
flags = ISO14B_SEND_CHAINING;
|
||||||
|
|
||||||
|
uint32_t time_wait = 0;
|
||||||
|
if (user_timeout > 0) {
|
||||||
|
|
||||||
|
flags |= ISO14B_SET_TIMEOUT;
|
||||||
|
if (user_timeout > MAX_14B_TIMEOUT) {
|
||||||
|
user_timeout = MAX_14B_TIMEOUT;
|
||||||
|
PrintAndLogEx(INFO, "set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
|
||||||
|
}
|
||||||
|
time_wait = (uint32_t)((13560000 / 1000 / (8 * 16)) * user_timeout); // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
|
||||||
|
}
|
||||||
|
|
||||||
// "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
|
// "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
|
||||||
// https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
|
// https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
|
||||||
// here length PM3_CMD_DATA_SIZE=512
|
// here length PM3_CMD_DATA_SIZE=512
|
||||||
if (datain)
|
if (datain)
|
||||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APDU | flags, (datainlen & 0xFFFF), 0, datain, datainlen & 0xFFFF);
|
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APDU | flags, (datainlen & 0xFFFF), time_wait, datain, datainlen & 0xFFFF);
|
||||||
else
|
else
|
||||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APDU | flags, 0, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APDU | flags, 0, time_wait, NULL, 0);
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, MAX(APDU_TIMEOUT, user_timeout))) {
|
||||||
uint8_t *recv = resp.data.asBytes;
|
uint8_t *recv = resp.data.asBytes;
|
||||||
int rlen = resp.oldarg[0];
|
int rlen = resp.oldarg[0];
|
||||||
uint8_t res = resp.oldarg[1];
|
uint8_t res = resp.oldarg[1];
|
||||||
|
@ -1488,7 +1619,7 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, bool
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, bool leave_signal_on, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
|
int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, bool leave_signal_on, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, int user_timeout) {
|
||||||
*dataoutlen = 0;
|
*dataoutlen = 0;
|
||||||
bool chaining = false;
|
bool chaining = false;
|
||||||
int res;
|
int res;
|
||||||
|
@ -1505,7 +1636,7 @@ static int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field
|
||||||
bool chainBlockNotLast = ((clen + vlen) < datainlen);
|
bool chainBlockNotLast = ((clen + vlen) < datainlen);
|
||||||
|
|
||||||
*dataoutlen = 0;
|
*dataoutlen = 0;
|
||||||
res = handle_14b_apdu(chainBlockNotLast, &datain[clen], vlen, v_activate_field, dataout, maxdataoutlen, dataoutlen, &chaining);
|
res = handle_14b_apdu(chainBlockNotLast, &datain[clen], vlen, v_activate_field, dataout, maxdataoutlen, dataoutlen, &chaining, user_timeout);
|
||||||
if (res) {
|
if (res) {
|
||||||
if (leave_signal_on == false)
|
if (leave_signal_on == false)
|
||||||
switch_off_field_14b();
|
switch_off_field_14b();
|
||||||
|
@ -1534,7 +1665,7 @@ static int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
res = handle_14b_apdu(false, datain, datainlen, activate_field, dataout, maxdataoutlen, dataoutlen, &chaining);
|
res = handle_14b_apdu(false, datain, datainlen, activate_field, dataout, maxdataoutlen, dataoutlen, &chaining, user_timeout);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
if (leave_signal_on == false) {
|
if (leave_signal_on == false) {
|
||||||
switch_off_field_14b();
|
switch_off_field_14b();
|
||||||
|
@ -1545,7 +1676,7 @@ static int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field
|
||||||
|
|
||||||
while (chaining) {
|
while (chaining) {
|
||||||
// I-block with chaining
|
// I-block with chaining
|
||||||
res = handle_14b_apdu(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining);
|
res = handle_14b_apdu(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining, user_timeout);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
if (leave_signal_on == false) {
|
if (leave_signal_on == false) {
|
||||||
switch_off_field_14b();
|
switch_off_field_14b();
|
||||||
|
@ -1593,6 +1724,7 @@ static int CmdHF14BAPDU(const char *Cmd) {
|
||||||
arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
|
arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
|
||||||
arg_int0("l", "le", "<int>", "Le apdu parameter if `m` parameter included"),
|
arg_int0("l", "le", "<int>", "Le apdu parameter if `m` parameter included"),
|
||||||
arg_strx1(NULL, "hex", "<hex>", "<APDU | data> if `m` parameter included"),
|
arg_strx1(NULL, "hex", "<hex>", "<APDU | data> if `m` parameter included"),
|
||||||
|
arg_int0(NULL, "timeout", "<dec>", "timeout in ms"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
@ -1652,6 +1784,7 @@ static int CmdHF14BAPDU(const char *Cmd) {
|
||||||
// len = data + PCB(1b) + CRC(2b)
|
// len = data + PCB(1b) + CRC(2b)
|
||||||
CLIGetHexBLessWithReturn(ctx, 8, data, &datalen, 1 + 2);
|
CLIGetHexBLessWithReturn(ctx, 8, data, &datalen, 1 + 2);
|
||||||
}
|
}
|
||||||
|
int user_timeout = arg_get_int_def(ctx, 9, -1);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s",
|
PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s",
|
||||||
|
@ -1669,7 +1802,7 @@ static int CmdHF14BAPDU(const char *Cmd) {
|
||||||
PrintAndLogEx(WARNING, "can't decode APDU.");
|
PrintAndLogEx(WARNING, "can't decode APDU.");
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = exchange_14b_apdu(data, datalen, activate_field, leave_signal_on, data, PM3_CMD_DATA_SIZE, &datalen);
|
int res = exchange_14b_apdu(data, datalen, activate_field, leave_signal_on, data, PM3_CMD_DATA_SIZE, &datalen, user_timeout);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1708,7 +1841,7 @@ static int CmdHF14BNdef(const char *Cmd) {
|
||||||
uint8_t aSELECT_AID[80];
|
uint8_t aSELECT_AID[80];
|
||||||
int aSELECT_AID_n = 0;
|
int aSELECT_AID_n = 0;
|
||||||
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
|
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
|
||||||
int res = exchange_14b_apdu(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
int res = exchange_14b_apdu(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen, -1);
|
||||||
if (res) {
|
if (res) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1734,7 +1867,7 @@ static int CmdHF14BNdef(const char *Cmd) {
|
||||||
uint8_t aSELECT_FILE_NDEF[30];
|
uint8_t aSELECT_FILE_NDEF[30];
|
||||||
int aSELECT_FILE_NDEF_n = 0;
|
int aSELECT_FILE_NDEF_n = 0;
|
||||||
param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
|
param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
|
||||||
res = exchange_14b_apdu(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
res = exchange_14b_apdu(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen, -1);
|
||||||
if (res)
|
if (res)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1749,7 +1882,7 @@ static int CmdHF14BNdef(const char *Cmd) {
|
||||||
uint8_t aREAD_NDEF[30];
|
uint8_t aREAD_NDEF[30];
|
||||||
int aREAD_NDEF_n = 0;
|
int aREAD_NDEF_n = 0;
|
||||||
param_gethex_to_eol("00b0000002", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
|
param_gethex_to_eol("00b0000002", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
|
||||||
res = exchange_14b_apdu(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
res = exchange_14b_apdu(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen, -1);
|
||||||
if (res) {
|
if (res) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1768,7 +1901,7 @@ static int CmdHF14BNdef(const char *Cmd) {
|
||||||
aREAD_NDEF_n = 0;
|
aREAD_NDEF_n = 0;
|
||||||
param_gethex_to_eol("00b00002", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
|
param_gethex_to_eol("00b00002", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
|
||||||
aREAD_NDEF[4] = offset;
|
aREAD_NDEF[4] = offset;
|
||||||
res = exchange_14b_apdu(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
res = exchange_14b_apdu(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen, -1);
|
||||||
if (res) {
|
if (res) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1816,14 +1949,14 @@ int CmdHF14B(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get and print all info known about any known 14b tag
|
// get and print all info known about any known 14b tag
|
||||||
int infoHF14B(bool verbose) {
|
int infoHF14B(bool verbose, bool do_aid_search) {
|
||||||
|
|
||||||
// try std 14b (atqb)
|
// try std 14b (atqb)
|
||||||
if (HF14B_Std_Info(verbose))
|
if (HF14B_Std_Info(verbose, do_aid_search))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// try ST 14b
|
// try ST 14b
|
||||||
if (HF14B_ST_Info(verbose))
|
if (HF14B_ST_Info(verbose, do_aid_search))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// try unknown 14b read commands (to be identified later)
|
// try unknown 14b read commands (to be identified later)
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
int CmdHF14B(const char *Cmd);
|
int CmdHF14B(const char *Cmd);
|
||||||
|
|
||||||
int infoHF14B(bool verbose);
|
int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, bool leave_signal_on, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, int user_timeout);
|
||||||
|
|
||||||
|
int infoHF14B(bool verbose, bool do_aid_search);
|
||||||
int readHF14B(bool verbose);
|
int readHF14B(bool verbose);
|
||||||
#endif
|
#endif
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue