Merge pull request #45 from RfidResearchGroup/master

Update
This commit is contained in:
mwalker33 2020-09-17 07:18:28 +10:00 committed by GitHub
commit d05714f58d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 73363 additions and 582 deletions

View file

@ -3,7 +3,10 @@ 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]
- Add `hf 14a config` to deal with badly configured cards: invalid ATQA/BCC/SAK (@doegox)" - Add options to `lf read` and `lf cmdread` (@doegox)
- Change options of `lf read` to match `lf cmdread`, this affects historical `d` and `s` options (@doegox)
- Add `hf waveshare` to upload picture to Waveshare NFC-Powered e-Paper (@doegox)
- Add `hf 14a config` to deal with badly configured cards: invalid ATQA/BCC/SAK (@doegox)
- Mikron JSC Russia Ultralight EV1 41 pages tag type support (@McEloff) - Mikron JSC Russia Ultralight EV1 41 pages tag type support (@McEloff)
- Add test for Ultralight gen2 magic 'hf search' (@McEloff) - Add test for Ultralight gen2 magic 'hf search' (@McEloff)
- Add test for Ultralight EV1 gen2 magic 'hf search' (@McEloff) - Add test for Ultralight EV1 gen2 magic 'hf search' (@McEloff)
@ -101,7 +104,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Change appveyor verbose (@doegox) - Change appveyor verbose (@doegox)
- Change `lf nexwatch demod` - now detects type, and show parity /chksum (@iceman1001) - Change `lf nexwatch demod` - now detects type, and show parity /chksum (@iceman1001)
- Change `lfsampling` - interruptible only when logging not yet triggered (@doegox) - Change `lfsampling` - interruptible only when logging not yet triggered (@doegox)
- Change `lf keri demod - more leanient when it comes to bits (@iceman1001) - Change `lf keri demod` - more leanient when it comes to bits (@iceman1001)
- fix, proper filtering of RL markers (@doegox) - fix, proper filtering of RL markers (@doegox)
- Change, clean deps [compiler trials] (@doegox) - Change, clean deps [compiler trials] (@doegox)
- Change, remove c99 restrictions [compiler trials] (@doegox) - Change, remove c99 restrictions [compiler trials] (@doegox)

View file

@ -32,8 +32,8 @@
|[Notes on frame format](/doc/new_frame_format.md)|[Notes on tracelog / wireshark](/doc/trace_notes.md)|[Notes on EMV](/doc/emv_notes.md)| |[Notes on frame format](/doc/new_frame_format.md)|[Notes on tracelog / wireshark](/doc/trace_notes.md)|[Notes on EMV](/doc/emv_notes.md)|
|[Notes on external flash](/doc/ext_flash_notes.md)|[Notes on loclass](/doc/loclass_notes.md)|[Notes on Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md)| |[Notes on external flash](/doc/ext_flash_notes.md)|[Notes on loclass](/doc/loclass_notes.md)|[Notes on Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md)|
|[Notes on file formats used with Proxmark3](/doc/extensions_notes.md)|[Notes on MFU binary format](/doc/mfu_binary_format_notes.md)|[Notes on FPGA & ARM](/doc/fpga_arm_notes.md)| |[Notes on file formats used with Proxmark3](/doc/extensions_notes.md)|[Notes on MFU binary format](/doc/mfu_binary_format_notes.md)|[Notes on FPGA & ARM](/doc/fpga_arm_notes.md)|
|[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)|| |[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)|[Notes on Magic cards](/doc/magic_cards_notes.md)|
|[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.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)|
## Build for non-RDV4 Proxmark3 platforms ## Build for non-RDV4 Proxmark3 platforms

View file

@ -1,6 +1,13 @@
version: 3.0.1.{build} version: 3.0.1.{build}
image: Visual Studio 2019 image: Visual Studio 2019
clone_folder: C:\ProxSpace\pm3 clone_folder: C:\ProxSpace\pm3\proxmark
environment:
proxspace_url: https://github.com/Gator96100/ProxSpace/archive/master.zip
proxspace_zip_file: \proxspace.zip
proxspace_zip_folder_name: ProxSpace-*
proxspace_path: \ProxSpace
proxspace_home_path: \ProxSpace\pm3
init: init:
- ps: >- - ps: >-
$psversiontable $psversiontable
@ -25,42 +32,79 @@ init:
# iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) # iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
clone_script: clone_script:
- ps: >- - ps: >-
Function ExecUpdate($Text, $firstStart) {
Write-Host "$Text" -NoNewLine
Start-Process "cmd.exe" "/c ""cd /D $env:proxspace_path && call msys2\ps\setup.cmd && msys2\msys2_shell.cmd -mingw64 -defterm -no-start -c ""exit"""""
$StartTime=[System.Environment]::TickCount
Start-Sleep -s 10
while($true) {
$cmdprocess = Get-Process "cmd" -ErrorAction SilentlyContinue
if (!$cmdprocess -Or $cmdprocess.HasExited) {
Write-Host "[ OK ]" -ForegroundColor Green
break
}
if ($firstStart -And (Test-Path "$env:proxspace_path\msys2\etc\pacman.conf.pacnew")) {
Start-Sleep -s 5
$tmp = $cmdprocess.CloseMainWindow()
Start-Sleep -s 5
Stop-Process -Name "cmd" -Force -ErrorAction SilentlyContinue
Write-Host "Exit by pacman.conf" -ForegroundColor Green
break
}
if ([System.Environment]::TickCount-$StartTime -gt 1000000) {
Write-host "Exit by timeout" -ForegroundColor Yellow
break
}
Start-Sleep -s 1
}
}
Write-Host "Removing ProxSpace..." -NoNewLine Write-Host "Removing ProxSpace..." -NoNewLine
$CloneTime=[System.Environment]::TickCount $CloneTime=[System.Environment]::TickCount
cd \ cd \
Remove-Item -Recurse -Force -Path c:\ProxSpace\* Remove-Item -Recurse -Force -Path $env:proxspace_path
Write-Host "[ OK ]" -ForegroundColor Green Write-Host "[ OK ]" -ForegroundColor Green
Write-Host "Download ProxSpace..." -NoNewLine
Write-Host "Git clone ProxSpace..." -NoNewLine
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
git clone -q https://github.com/Gator96100/ProxSpace c:\ProxSpace
Invoke-WebRequest "$env:proxspace_url" -outfile "$env:proxspace_zip_file"
Write-Host "[ OK ]" -ForegroundColor Green
if(!(Test-Path -Path C:\ProxSpace\pm3)){
New-Item -ItemType Directory -Force -Path C:\ProxSpace\pm3
}
Write-Host "Removing pm3 dir..." -NoNewLine
Remove-Item -Recurse -Force -Path c:\ProxSpace\pm3\*
Write-Host "[ OK ]" -ForegroundColor Green Write-Host "[ OK ]" -ForegroundColor Green
Write-Host "Removing ps startup_check.sh ..." -NoNewLine Write-Host "Extracting ProxSpace..." -NoNewLine
Remove-Item -Recurse -Force -Path c:\ProxSpace\msys2\ps\startup_checks.sh Expand-Archive -LiteralPath "$env:proxspace_zip_file" -DestinationPath "\"
Remove-Item "$env:proxspace_zip_file"
Write-Host "[ OK ]" -ForegroundColor Green Write-Host "[ OK ]" -ForegroundColor Green
Write-Host "Renaming ProxSpace folder..." -NoNewLine
Get-ChildItem -Path "\$env:proxspace_zip_folder_name" | Rename-Item -NewName (Split-Path $env:proxspace_path -Leaf)
Write-Host "[ OK ]" -ForegroundColor Gree
ExecUpdate "Initial msys2 startup..." $true
ExecUpdate "Installing required packages..." $false
$psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "$env:proxspace_path\msys2\ps\09-proxspace_setup.post").Line.Split("""")[1]
Write-Host "ProxSpace version: $psversion" -ForegroundColor Yellow
Write-Host "Cloning repository <$env:appveyor_repo_name> to $env:appveyor_build_folder ..." -NoNewLine Write-Host "Cloning repository <$env:appveyor_repo_name> to $env:appveyor_build_folder ..." -NoNewLine
if(-not $env:appveyor_pull_request_number) { if(-not $env:appveyor_pull_request_number) {
@ -73,134 +117,45 @@ clone_script:
git fetch -q origin +refs/pull/$env:appveyor_pull_request_number/merge: git fetch -q origin +refs/pull/$env:appveyor_pull_request_number/merge:
git checkout -qf FETCH_HEAD git checkout -qf FETCH_HEAD
} }
Write-Host "[ OK ]" -ForegroundColor Green Write-Host "[ OK ]" -ForegroundColor Green
Write-Host "Fill msys2\etc\fstab file..." -NoNewLine
New-Item c:\ProxSpace\msys2\etc\fstab -type file -force -value "# For a description of the file format, see the Users Guide`n# http://cygwin.com/cygwin-ug-net/using.html#mount-table`nnone / cygdrive binary,posix=0,noacl,user 0 0 `nC:\ProxSpace\pm3 /pm3 ntfs noacl 0 0 `nC:\ProxSpace\gcc-arm-none-eabi /gcc-arm-none-eabi ntfs noacl 0 0 `n"
Write-Host "[ OK ]" -ForegroundColor Green
Write-Host "Update msys2 packages..."
$env:Path = "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path"
Function ExecUpdate($Name, $Cmd, $ErrorLine) {
Write-Host "Exec [$Name]... " -NoNewLine
#--- begin Job
$Job = Start-Job -Name "$Name" -ScriptBlock {
$env:Path = "C:\ProxSpace\msys\bin;$env:Path"
Set-Location $using:PWD
$sb=[scriptblock]::Create("$using:Cmd")
#execute scriptblock
$Cond=&$sb
return $Cond
}
#--- end Job
$JobTime=[System.Environment]::TickCount
while($true) {
Try {
$Res = Receive-Job -Job $Job -Keep 2>&1 6>&1
}
Catch {
$Res = ""
Write-host "error in Receive-Job"
}
if ($Res -is "String" -and $Res -like "*$ErrorLine*"){
Write-host "Exit by stop phrase" -ForegroundColor Green
break
}
if ($Res -is [Object]){
[bool]$needexit = $false
ForEach($line in $Res){
if ($line -like "*$ErrorLine*"){
Write-host "Exit by stop phrase [obj]" -ForegroundColor Green
$needexit = $true
break
}
}
if ($needexit) {
break
}
}
if(Wait-Job $Job -Timeout 5){
Write-host "Exit by end job" -ForegroundColor Green
break
}
if ([System.Environment]::TickCount-$JobTime -gt 1000000) {
Write-host "Exit by timeout" -ForegroundColor Yellow
break
}
}
Remove-Job -Force $Job
}
cd C:\ProxSpace\
C:\ProxSpace\msys2\ps\setup.cmd
ExecUpdate "update1" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2"
ExecUpdate "update2" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2"
Add-AppveyorMessage -Message "ProxSpace download and update took $(([System.Environment]::TickCount-$CloneTime) / 1000) sec" -Category Information Add-AppveyorMessage -Message "ProxSpace download and update took $(([System.Environment]::TickCount-$CloneTime) / 1000) sec" -Category Information
Write-Host "Update " -NoNewLine
Write-Host "[ OK ]" -ForegroundColor Green
install: install:
build_script: build_script:
- ps: >- - ps: >-
$env:Path="C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;c:\Python38;c:\Python38\Scripts;$env:Path"
$env:MINGW_HOME="C:\ProxSpace\msys2\mingw32" $pmfolder = Split-Path $env:appveyor_build_folder -Leaf
$env:MSYS_HOME="C:\ProxSpace\msys2" Function ExecMinGWCmd($Cmd) {
cd $env:proxspace_path
$env:MSYSTEM="MINGW32" msys2\msys2_shell.cmd -mingw64 -defterm -no-start -c "cd $pmfolder && $Cmd"
}
$env:MINGW_PREFIX="/mingw32"
$env:SHELL="/bin/bash"
$env:MSYSTEM_CHOST="i686-w64-mingw32"
cd C:\ProxSpace\pm3
Write-Host "---------- make ----------" -ForegroundColor Yellow Write-Host "---------- make ----------" -ForegroundColor Yellow
$TestTime=[System.Environment]::TickCount $TestTime=[System.Environment]::TickCount
#make #make
bash -c -i 'echo $PATH;pwd;make clean;make V=1' cd $env:proxspace_path
msys2\ps\setup.cmd
ExecMinGWCmd "make clean;make V=1"
#some checks #some checks
if(!(Test-Path C:\ProxSpace\pm3\client\proxmark3.exe)){ if(!(Test-Path "$env:proxspace_home_path\$pmfolder\client\proxmark3.exe")){
throw "Main file proxmark3.exe not exists." throw "Main file proxmark3.exe not exists."
} }
cd c:\ProxSpace\pm3 ExecMinGWCmd 'make check'
bash -c -i 'make check'
$testspass = ($LASTEXITCODE -eq 0) $testspass = ($LASTEXITCODE -eq 0)
@ -219,11 +174,9 @@ build_script:
$TestTime=[System.Environment]::TickCount $TestTime=[System.Environment]::TickCount
bash -c -i 'pwd;make clean;make PLATFORM_EXTRAS=BTADDON' ExecMinGWCmd 'make clean;make V=1 PLATFORM_EXTRAS=BTADDON'
cd c:\ProxSpace\pm3 ExecMinGWCmd 'make check'
bash -c -i 'make check'
$testspass = ($LASTEXITCODE -eq 0) $testspass = ($LASTEXITCODE -eq 0)
@ -239,19 +192,17 @@ build_script:
Write-Host "---------- make clean ----------" -ForegroundColor Yellow Write-Host "---------- make clean ----------" -ForegroundColor Yellow
bash -c -i 'make clean' ExecMinGWCmd 'make clean'
Write-Host "---------- cmake ----------" -ForegroundColor Yellow Write-Host "---------- cmake ----------" -ForegroundColor Yellow
$TestTime=[System.Environment]::TickCount $TestTime=[System.Environment]::TickCount
cmd.exe /c 'C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start -c "mkdir -p client/build; cd client/build; cmake -G""MSYS Makefiles"" ..; make VERBOSE=1;"' ExecMinGWCmd 'mkdir -p client/build; cd client/build; cmake -G""MSYS Makefiles"" ..; make VERBOSE=1;'
Write-Host "---------- cmake tests ----------" -ForegroundColor Yellow Write-Host "---------- cmake tests ----------" -ForegroundColor Yellow
cd c:\ProxSpace\pm3 ExecMinGWCmd './tools/pm3_tests.sh --clientbin client/build/proxmark3.exe client'
bash -c -i './tools/pm3_tests.sh --clientbin client/build/proxmark3.exe client'
$testspass = ($LASTEXITCODE -eq 0) $testspass = ($LASTEXITCODE -eq 0)

View file

@ -759,8 +759,8 @@ static void PacketReceived(PacketCommandNG *packet) {
} }
case CMD_LF_ACQ_RAW_ADC: { case CMD_LF_ACQ_RAW_ADC: {
struct p { struct p {
bool verbose; uint32_t samples : 31;
uint32_t samples; bool verbose : 1;
} PACKED; } PACKED;
struct p *payload = (struct p *)packet->data.asBytes; struct p *payload = (struct p *)packet->data.asBytes;
uint32_t bits = SampleLF(payload->verbose, payload->samples); uint32_t bits = SampleLF(payload->verbose, payload->samples);
@ -772,9 +772,11 @@ static void PacketReceived(PacketCommandNG *packet) {
uint32_t delay; uint32_t delay;
uint16_t ones; uint16_t ones;
uint16_t zeros; uint16_t zeros;
uint32_t samples : 31;
bool verbose : 1;
} PACKED; } PACKED;
struct p *payload = (struct p *)packet->data.asBytes; struct p *payload = (struct p *)packet->data.asBytes;
ModThenAcquireRawAdcSamples125k(payload->delay, payload->zeros, payload->ones, packet->data.asBytes + 8); ModThenAcquireRawAdcSamples125k(payload->delay, payload->zeros, payload->ones, packet->data.asBytes + sizeof(struct p), payload->verbose, payload->samples);
break; break;
} }
case CMD_LF_SNIFF_RAW_ADC: { case CMD_LF_SNIFF_RAW_ADC: {

View file

@ -134,11 +134,11 @@ 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......%s%s%s", (hf14aconfig.forceanticol == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forceanticol == 1) ? _RED_("Yes: Always do anticol") : "", (hf14aconfig.forceanticol == 2) ? _RED_("Yes: Always skip anticol") : ""); Dbprintf("[a] Anticol override......%i: %s%s%s", hf14aconfig.forceanticol, (hf14aconfig.forceanticol == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forceanticol == 1) ? _RED_("Yes: Always do anticol") : "", (hf14aconfig.forceanticol == 2) ? _RED_("Yes: Always skip anticol") : "");
Dbprintf("[b] BCC override..........%s%s%s", (hf14aconfig.forcebcc == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcebcc == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcebcc == 2) ? _RED_("Yes: Always use card BCC") : ""); Dbprintf("[b] BCC override..........%i: %s%s%s", hf14aconfig.forcebcc, (hf14aconfig.forcebcc == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcebcc == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcebcc == 2) ? _RED_("Yes: Always use card BCC") : "");
Dbprintf("[2] CL2 override..........%s%s%s", (hf14aconfig.forcecl2 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl2 == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcecl2 == 2) ? _RED_("Yes: Always skip CL2") : ""); Dbprintf("[2] CL2 override..........%i: %s%s%s", hf14aconfig.forcecl2, (hf14aconfig.forcecl2 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl2 == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcecl2 == 2) ? _RED_("Yes: Always skip CL2") : "");
Dbprintf("[3] CL3 override..........%s%s%s", (hf14aconfig.forcecl3 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl3 == 1) ? _RED_("Yes: Always do CL3") : "", (hf14aconfig.forcecl3 == 2) ? _RED_("Yes: Always skip CL3") : ""); Dbprintf("[3] CL3 override..........%i: %s%s%s", hf14aconfig.forcecl3, (hf14aconfig.forcecl3 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl3 == 1) ? _RED_("Yes: Always do CL3") : "", (hf14aconfig.forcecl3 == 2) ? _RED_("Yes: Always skip CL3") : "");
Dbprintf("[r] RATS override.........%s%s%s", (hf14aconfig.forcerats == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcerats == 1) ? _RED_("Yes: Always do RATS") : "", (hf14aconfig.forcerats == 2) ? _RED_("Yes: Always skip RATS") : ""); Dbprintf("[r] RATS override.........%i: %s%s%s", hf14aconfig.forcerats, (hf14aconfig.forcerats == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcerats == 1) ? _RED_("Yes: Always do RATS") : "", (hf14aconfig.forcerats == 2) ? _RED_("Yes: Always skip RATS") : "");
} }
/** /**
@ -899,13 +899,15 @@ bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) {
uint16_t check = 0; uint16_t check = 0;
for (;;) { for (;;) {
if (check == 1000) { if (check == 4000) {
if (BUTTON_PRESS() || data_available()) // if (BUTTON_PRESS() || data_available())
if (BUTTON_PRESS())
return false; return false;
check = 0; check = 0;
WDT_HIT();
} }
++check; ++check;
WDT_HIT();
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;
@ -981,11 +983,15 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
// Prepare the optional second SAK (for 7 byte UID), drop the cascade bit // Prepare the optional second SAK (for 7 byte UID), drop the cascade bit
static uint8_t rSAKc2[3] = { 0x00 }; static uint8_t rSAKc2[3] = { 0x00 };
// dummy ATS (pseudo-ATR), answer to RATS // dummy ATS (pseudo-ATR), answer to RATS
static uint8_t rRATS[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // static uint8_t rRATS[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 };
static uint8_t rRATS[] = { 0x05, 0x75, 0x80, 0x60, 0x02, 0x00, 0x00 };
// GET_VERSION response for EV1/NTAG // GET_VERSION response for EV1/NTAG
static uint8_t rVERSION[10] = { 0x00 }; static uint8_t rVERSION[10] = { 0x00 };
// READ_SIG response for EV1/NTAG // READ_SIG response for EV1/NTAG
static uint8_t rSIGN[34] = { 0x00 }; static uint8_t rSIGN[34] = { 0x00 };
// PPS respoonse
static uint8_t rPPS[3] = { 0xD0 };
switch (tagType) { switch (tagType) {
case 1: { // MIFARE Classic 1k case 1: { // MIFARE Classic 1k
@ -1059,12 +1065,19 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
sak = 0x18; sak = 0x18;
} }
break; break;
case 9 : { // FM11RF005SH (Shanghai Metro) case 9: { // FM11RF005SH (Shanghai Metro)
rATQA[0] = 0x03; rATQA[0] = 0x03;
rATQA[1] = 0x00; rATQA[1] = 0x00;
sak = 0x0A; sak = 0x0A;
} }
break; break;
case 10: { // JCOP31/41 Rothult
rATQA[0] = 0x42;
rATQA[1] = 0x00;
sak = 0x00;
}
break;
default: { default: {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Error: unknown tagtype (%d)", tagType); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Error: unknown tagtype (%d)", tagType);
return false; return false;
@ -1115,13 +1128,20 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
return false; return false;
} }
// Calculate the BitCountCheck (BCC) for the first 4 bytes of the UID. // Calculate BCC for the first 4 bytes of the UID.
rUIDc1[4] = rUIDc1[0] ^ rUIDc1[1] ^ rUIDc1[2] ^ rUIDc1[3]; rUIDc1[4] = rUIDc1[0] ^ rUIDc1[1] ^ rUIDc1[2] ^ rUIDc1[3];
rSAKc1[0] = sak;
AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2);
rSAKc2[0] = sak & 0xFB; if (tagType == 10) {
rSAKc1[0] = 0x04;
rSAKc2[0] = 0x20;
} else {
rSAKc1[0] = sak;
rSAKc2[0] = sak & 0xFB;
}
// crc
AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2);
AddCrc14A(rSAKc2, sizeof(rSAKc2) - 2); AddCrc14A(rSAKc2, sizeof(rSAKc2) - 2);
// Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present, // Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present,
@ -1130,22 +1150,26 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
// TC(1) = 0x02: CID supported, NAD not supported // TC(1) = 0x02: CID supported, NAD not supported
AddCrc14A(rRATS, sizeof(rRATS) - 2); AddCrc14A(rRATS, sizeof(rRATS) - 2);
#define TAG_RESPONSE_COUNT 8 AddCrc14A(rPPS, sizeof(rPPS) - 2);
#define TAG_RESPONSE_COUNT 9
static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = { static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = {
{ .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type { .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type
{ .response = rUIDc1, .response_n = sizeof(rUIDc1) }, // Anticollision cascade1 - respond with uid { .response = rUIDc1, .response_n = sizeof(rUIDc1) }, // Anticollision cascade1 - respond with uid
{ .response = rUIDc2, .response_n = sizeof(rUIDc2) }, // Anticollision cascade2 - respond with 2nd half of uid if asked { .response = rUIDc2, .response_n = sizeof(rUIDc2) }, // Anticollision cascade2 - respond with 2nd half of uid if asked
{ .response = rSAKc1, .response_n = sizeof(rSAKc1) }, // Acknowledge select - cascade 1 { .response = rSAKc1, .response_n = sizeof(rSAKc1) }, // Acknowledge select - cascade 1
{ .response = rSAKc2, .response_n = sizeof(rSAKc2) }, // Acknowledge select - cascade 2 { .response = rSAKc2, .response_n = sizeof(rSAKc2) }, // Acknowledge select - cascade 2
{ .response = rRATS, .response_n = sizeof(rRATS) }, // dummy ATS (pseudo-ATR), answer to RATS { .response = rRATS, .response_n = sizeof(rRATS) }, // dummy ATS (pseudo-ATR), answer to RATS
{ .response = rVERSION, .response_n = sizeof(rVERSION) }, // EV1/NTAG GET_VERSION response { .response = rVERSION, .response_n = sizeof(rVERSION) }, // EV1/NTAG GET_VERSION response
{ .response = rSIGN, .response_n = sizeof(rSIGN) } // EV1/NTAG READ_SIG response { .response = rSIGN, .response_n = sizeof(rSIGN) }, // EV1/NTAG READ_SIG response
{ .response = rPPS, .response_n = sizeof(rPPS) } // PPS response
}; };
// "precompile" responses. There are 8 predefined responses with a total of 68 bytes data to transmit. // "precompile" responses. There are 9 predefined responses with a total of 72 bytes data to transmit.
// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction) // Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
// 68 * 8 data bits, 68 * 1 parity bits, 8 start bits, 8 stop bits, 8 correction bits -- 636 bytes buffer // 72 * 8 data bits, 72 * 1 parity bits, 9 start bits, 9 stop bits, 9 correction bits -- 677 bytes buffer
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 636 #define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 675
// 576 + 72 + 9 + 9 + 9 == 675
uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
// modulation buffer pointer and current buffer free space size // modulation buffer pointer and current buffer free space size
@ -1173,7 +1197,7 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
#define RATS 5 #define RATS 5
#define VERSION 6 #define VERSION 6
#define SIGNATURE 7 #define SIGNATURE 7
#define PPS 8
return true; return true;
} }
@ -1232,6 +1256,8 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
// We need to listen to the high-frequency, peak-detected path. // We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
iso14a_set_timeout(201400); // 106 * 19ms default
int len = 0; int len = 0;
// To control where we are in the protocol // To control where we are in the protocol
@ -1246,8 +1272,8 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
#define ORDER_SELECT_CL2 30 #define ORDER_SELECT_CL2 30
#define ORDER_EV1_COMP_WRITE 40 #define ORDER_EV1_COMP_WRITE 40
#define ORDER_RATS 70 #define ORDER_RATS 70
uint8_t order = ORDER_NONE;
uint8_t order = ORDER_NONE;
int retval = PM3_SUCCESS; int retval = PM3_SUCCESS;
// Just to allow some checks // Just to allow some checks
@ -1258,27 +1284,26 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
// compatible write block number // compatible write block number
uint8_t wrblock = 0; uint8_t wrblock = 0;
bool odd_reply = true;
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
LED_A_ON(); LED_A_ON();
// main loop
for (;;) { for (;;) {
WDT_HIT(); WDT_HIT();
tag_response_info_t *p_response = NULL;
// Clean receive command buffer // Clean receive command buffer
if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { if (GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len) == false) {
Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen());
retval = PM3_EOPABORTED; retval = PM3_EOPABORTED;
break; break;
} }
tag_response_info_t *p_response = NULL;
// Okay, look at the command now.
int lastorder = order;
//
// we need to check "ordered" states before, because received data may be same to any command - is wrong!!! // we need to check "ordered" states before, because received data may be same to any command - is wrong!!!
//
if (order == ORDER_EV1_COMP_WRITE && len == 18) { if (order == ORDER_EV1_COMP_WRITE && len == 18) {
// MIFARE_ULC_COMP_WRITE part 2 // MIFARE_ULC_COMP_WRITE part 2
// 16 bytes data + 2 bytes crc, only least significant 4 bytes are written // 16 bytes data + 2 bytes crc, only least significant 4 bytes are written
@ -1361,28 +1386,22 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
order = ORDER_NONE; // back to work state order = ORDER_NONE; // back to work state
p_response = NULL; p_response = NULL;
// } else if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST, but in HALTED, skip
// now check commands in received buffer odd_reply = !odd_reply;
// if (odd_reply)
p_response = &responses[ATQA];
} else if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST
p_response = &responses[ATQA];
order = ORDER_REQA;
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP } else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP
p_response = &responses[ATQA]; p_response = &responses[ATQA];
order = ORDER_WUPA;
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { // Received request for UID (cascade 1) } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { // Received request for UID (cascade 1)
p_response = &responses[UIDC1]; p_response = &responses[UIDC1];
order = ORDER_SELECT_ALL_CL1;
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 2) { // Received request for UID (cascade 2) } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 2) { // Received request for UID (cascade 2)
p_response = &responses[UIDC2]; p_response = &responses[UIDC2];
order = ORDER_SELECT_ALL_CL2;
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1) } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1)
p_response = &responses[SAKC1]; p_response = &responses[SAKC1];
order = ORDER_SELECT_CL1;
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 9) { // Received a SELECT (cascade 2) } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 9) { // Received a SELECT (cascade 2)
p_response = &responses[SAKC2]; p_response = &responses[SAKC2];
order = ORDER_SELECT_CL2; } else if (receivedCmd[0] == ISO14443A_CMD_PPS) {
p_response = &responses[PPS];
} else if (receivedCmd[0] == ISO14443A_CMD_READBLOCK && len == 4) { // Received a (plain) READ } else if (receivedCmd[0] == ISO14443A_CMD_READBLOCK && len == 4) { // Received a (plain) READ
uint8_t block = receivedCmd[1]; uint8_t block = receivedCmd[1];
// if Ultralight or NTAG (4 byte blocks) // if Ultralight or NTAG (4 byte blocks)
@ -1410,8 +1429,6 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
emlGetMemBt(emdata, block, 16); emlGetMemBt(emdata, block, 16);
AddCrc14A(emdata, 16); AddCrc14A(emdata, 16);
EmSendCmd(emdata, sizeof(emdata)); EmSendCmd(emdata, sizeof(emdata));
// EmSendCmd(data+(4*receivedCmd[1]),16);
// Dbprintf("Read request from reader: %x %x",receivedCmd[0],receivedCmd[1]);
// We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below
p_response = NULL; p_response = NULL;
} }
@ -1433,8 +1450,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
p_response = NULL; p_response = NULL;
} else if (receivedCmd[0] == MIFARE_ULC_WRITE && len == 8 && (tagType == 2 || tagType == 7)) { // Received a WRITE } else if (receivedCmd[0] == MIFARE_ULC_WRITE && len == 8 && (tagType == 2 || tagType == 7)) { // Received a WRITE
// cmd + block + 4 bytes data + 2 bytes crc // cmd + block + 4 bytes data + 2 bytes crc
bool isCrcCorrect = CheckCrc14A(receivedCmd, len); if (CheckCrc14A(receivedCmd, len)) {
if (isCrcCorrect) {
uint8_t block = receivedCmd[1]; uint8_t block = receivedCmd[1];
if (block > pages) { if (block > pages) {
// send NACK 0x0 == invalid argument // send NACK 0x0 == invalid argument
@ -1452,8 +1468,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
p_response = NULL; p_response = NULL;
} else if (receivedCmd[0] == MIFARE_ULC_COMP_WRITE && len == 4 && (tagType == 2 || tagType == 7)) { } else if (receivedCmd[0] == MIFARE_ULC_COMP_WRITE && len == 4 && (tagType == 2 || tagType == 7)) {
// cmd + block + 2 bytes crc // cmd + block + 2 bytes crc
bool isCrcCorrect = CheckCrc14A(receivedCmd, len); if (CheckCrc14A(receivedCmd, len)) {
if (isCrcCorrect) {
wrblock = receivedCmd[1]; wrblock = receivedCmd[1];
if (wrblock > pages) { if (wrblock > pages) {
// send NACK 0x0 == invalid argument // send NACK 0x0 == invalid argument
@ -1538,7 +1553,6 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
p_response = NULL; p_response = NULL;
} else { } else {
p_response = &responses[RATS]; p_response = &responses[RATS];
order = ORDER_RATS;
} }
} else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
@ -1566,73 +1580,103 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
AddCrc14A(cmd, sizeof(cmd) - 2); AddCrc14A(cmd, sizeof(cmd) - 2);
EmSendCmd(cmd, sizeof(cmd)); EmSendCmd(cmd, sizeof(cmd));
p_response = NULL; p_response = NULL;
} else { } else {
// Check for ISO 14443A-4 compliant commands, look at left nibble
switch (receivedCmd[0]) { // clear old dynamic responses
case 0x02: dynamic_response_info.response_n = 0;
case 0x03: { // IBlock (command no CID) dynamic_response_info.modulation_n = 0;
// ST25TA512B IKEA Rothult
if (tagType == 10) {
// we replay 90 00 for all commands but the read bin and we deny the verify cmd.
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, "\x00\x1b\xd1\x01\x17\x54\x02\x7a\x68\xa2\x34\xcb\xd0\xe2\x03\xc7\x3e\x62\x0b\xe8\xc6\x3c\x85\x2c\xc5\x31\x31\x31\x32\x90\x00", 31);
dynamic_response_info.response_n = 32;
} 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[2] = 0x00;
dynamic_response_info.response_n = 3;
} else {
dynamic_response_info.response[0] = receivedCmd[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;
} }
break; } else {
case 0x0B:
case 0x0A: { // IBlock (command CID)
dynamic_response_info.response[0] = receivedCmd[0];
dynamic_response_info.response[1] = 0x00;
dynamic_response_info.response[2] = 0x90;
dynamic_response_info.response[3] = 0x00;
dynamic_response_info.response_n = 4;
}
break;
case 0x1A: // Check for ISO 14443A-4 compliant commands, look at left nibble
case 0x1B: { // Chaining command switch (receivedCmd[0]) {
dynamic_response_info.response[0] = 0xaa | ((receivedCmd[0]) & 1); case 0x02:
dynamic_response_info.response_n = 2; case 0x03: { // IBlock (command no CID)
} dynamic_response_info.response[0] = receivedCmd[0];
break; dynamic_response_info.response[1] = 0x90;
dynamic_response_info.response[2] = 0x00;
case 0xAA: dynamic_response_info.response_n = 3;
case 0xBB: {
dynamic_response_info.response[0] = receivedCmd[0] ^ 0x11;
dynamic_response_info.response_n = 2;
}
break;
case 0xBA: { // ping / pong
dynamic_response_info.response[0] = 0xAB;
dynamic_response_info.response[1] = 0x00;
dynamic_response_info.response_n = 2;
}
break;
case 0xCA:
case 0xC2: { // Readers sends deselect command
dynamic_response_info.response[0] = 0xCA;
dynamic_response_info.response[1] = 0x00;
dynamic_response_info.response_n = 2;
}
break;
default: {
// Never seen this command before
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("Received unknown command (len=%d):", len);
Dbhexdump(len, receivedCmd, false);
} }
// Do not respond break;
dynamic_response_info.response_n = 0; case 0x0B:
order = ORDER_NONE; // back to work state case 0x0A: { // IBlock (command CID)
} dynamic_response_info.response[0] = receivedCmd[0];
break; dynamic_response_info.response[1] = 0x00;
} dynamic_response_info.response[2] = 0x90;
dynamic_response_info.response[3] = 0x00;
dynamic_response_info.response_n = 4;
}
break;
case 0x1A:
case 0x1B: { // Chaining command
dynamic_response_info.response[0] = 0xaa | ((receivedCmd[0]) & 1);
dynamic_response_info.response_n = 2;
}
break;
case 0xAA:
case 0xBB: {
dynamic_response_info.response[0] = receivedCmd[0] ^ 0x11;
dynamic_response_info.response_n = 2;
}
break;
case 0xBA: { // ping / pong
dynamic_response_info.response[0] = 0xAB;
dynamic_response_info.response[1] = 0x00;
dynamic_response_info.response_n = 2;
}
break;
case 0xCA:
case 0xC2: { // Readers sends deselect command
dynamic_response_info.response[0] = 0xCA;
dynamic_response_info.response[1] = 0x00;
dynamic_response_info.response_n = 2;
}
break;
default: {
// Never seen this command before
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("Received unknown command (len=%d):", len);
Dbhexdump(len, receivedCmd, false);
}
// Do not respond
dynamic_response_info.response_n = 0;
order = ORDER_NONE; // back to work state
}
break;
}
}
if (dynamic_response_info.response_n > 0) { if (dynamic_response_info.response_n > 0) {
// Copy the CID from the reader query // Copy the CID from the reader query
dynamic_response_info.response[1] = receivedCmd[1]; if (tagType != 10)
dynamic_response_info.response[1] = receivedCmd[1];
// Add CRC bytes, always used in ISO 14443A-4 compliant cards // Add CRC bytes, always used in ISO 14443A-4 compliant cards
AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n); AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n);
@ -1648,16 +1692,15 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
} }
// Count number of wakeups received after a halt // Count number of wakeups received after a halt
if (order == ORDER_WUPA && lastorder == ORDER_HALTED) { happened++; } // if (order == ORDER_WUPA && lastorder == ORDER_HALTED) { happened++; }
// Count number of other messages after a halt // Count number of other messages after a halt
if (order != ORDER_WUPA && lastorder == ORDER_HALTED) { happened2++; } // if (order != ORDER_WUPA && lastorder == ORDER_HALTED) { happened2++; }
cmdsRecvd++; cmdsRecvd++;
if (p_response != NULL) { // Send response
EmSendPrecompiledCmd(p_response); EmSendPrecompiledCmd(p_response);
}
} }
switch_off(); switch_off();
@ -1958,7 +2001,7 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
volatile uint8_t b; volatile uint8_t b;
uint16_t i = 0; uint16_t i = 0;
uint32_t ThisTransferTime; uint32_t ThisTransferTime;
bool correctionNeeded; bool correction_needed;
// Modulate Manchester // Modulate Manchester
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);
@ -1966,21 +2009,23 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
// Include correction bit if necessary // Include correction bit if necessary
if (Uart.bitCount == 7) { if (Uart.bitCount == 7) {
// Short tags (7 bits) don't have parity, determine the correct value from MSB // Short tags (7 bits) don't have parity, determine the correct value from MSB
correctionNeeded = Uart.output[0] & 0x40; correction_needed = Uart.output[0] & 0x40;
} else { } else {
// The parity bits are left-aligned // The parity bits are left-aligned
correctionNeeded = Uart.parity[(Uart.len - 1) / 8] & (0x80 >> ((Uart.len - 1) & 7)); correction_needed = Uart.parity[(Uart.len - 1) / 8] & (0x80 >> ((Uart.len - 1) & 7));
} }
// 1236, so correction bit needed // 1236, so correction bit needed
i = (correctionNeeded) ? 0 : 1; i = (correction_needed) ? 0 : 1;
// clear receiving shift register and holding register // clear receiving shift register and holding register
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY));
b = AT91C_BASE_SSC->SSC_RHR; b = AT91C_BASE_SSC->SSC_RHR;
(void) b; (void) b;
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); /*
b = AT91C_BASE_SSC->SSC_RHR; while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY));
(void) b; b = AT91C_BASE_SSC->SSC_THR;
(void) b;
*/
// wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line)
for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never
@ -2000,22 +2045,24 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
} }
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { /*
b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
(void)b; b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
} (void)b;
}
*/
} }
// Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again:
uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3; uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3;
for (i = 0; i <= fpga_queued_bits / 8 + 1;) { for (i = 0; i <= (fpga_queued_bits >> 3) + 1;) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = SEC_F; AT91C_BASE_SSC->SSC_THR = SEC_F;
FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
i++; i++;
} }
} }
LastTimeProxToAirStart = ThisTransferTime + (correctionNeeded ? 8 : 0); LastTimeProxToAirStart = ThisTransferTime + (correction_needed ? 8 : 0);
return 0; return 0;
} }
@ -2069,6 +2116,7 @@ int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision) {
} }
int EmSendPrecompiledCmd(tag_response_info_t *p_response) { int EmSendPrecompiledCmd(tag_response_info_t *p_response) {
if (p_response == NULL) return 0;
int ret = EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n); int ret = EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n);
// do the tracing for the previous reader request and this tag answer: // do the tracing for the previous reader request and this tag answer:
uint8_t par[MAX_PARITY_SIZE] = {0x00}; uint8_t par[MAX_PARITY_SIZE] = {0x00};
@ -2489,7 +2537,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
} else if (hf14aconfig.forcebcc == 1) { } else if (hf14aconfig.forcebcc == 1) {
sel_uid[6] = bcc; sel_uid[6] = bcc;
} // else use card BCC } // else use card BCC
Dbprintf("Using BCC=" _YELLOW_("0x%02x") " to perform anticollision", sel_uid[6]); Dbprintf("Using BCC%d=" _YELLOW_("0x%02x") " to perform anticollision", cascade_level, sel_uid[6]);
} }
} else { } else {
memcpy(sel_uid + 2, uid_resp, 4); // the provided UID memcpy(sel_uid + 2, uid_resp, 4); // the provided UID

View file

@ -53,7 +53,7 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
#define RWD_TIME_PAUSE 4 /* 18.9us */ #define RWD_TIME_PAUSE 4 /* 18.9us */
#define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */ #define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */
#define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */ #define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */
#define RWD_CMD_TIMEOUT 120 /* 120 * 99.1us (arbitrary value) */ #define RWD_CMD_TIMEOUT 400 /* 120 * 99.1us (arbitrary value) */
#define RWD_MIN_FRAME_LEN 6 /* Shortest frame is 6 bits */ #define RWD_MIN_FRAME_LEN 6 /* Shortest frame is 6 bits */
#define RWD_MAX_FRAME_LEN 23 /* Longest frame is 23 bits */ #define RWD_MAX_FRAME_LEN 23 /* Longest frame is 23 bits */
@ -68,6 +68,7 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
// Note: inlining this function would fail with -Os // Note: inlining this function would fail with -Os
static bool wait_for(bool value, const uint32_t timeout) { static bool wait_for(bool value, const uint32_t timeout) {
while ((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) { while ((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) {
WDT_HIT();
if (GetCountSspClk() > timeout) { if (GetCountSspClk() > timeout) {
return false; return false;
} }
@ -215,7 +216,7 @@ static int32_t rx_frame(uint8_t *len) {
last_frame_end -= 2; last_frame_end -= 2;
// wait for first pause (start of frame) // wait for first pause (start of frame)
for (uint8_t i = 0; true; ++i) { for (uint16_t i = 0; true; ++i) {
// increment prng every TAG_BIT_PERIOD // increment prng every TAG_BIT_PERIOD
last_frame_end += TAG_BIT_PERIOD; last_frame_end += TAG_BIT_PERIOD;
legic_prng_forward(1); legic_prng_forward(1);

View file

@ -383,7 +383,7 @@ void loadT55xxConfig(void) {
* @param period_1 * @param period_1
* @param command (in binary char array) * @param command (in binary char array)
*/ */
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command) { void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command, bool verbose, uint32_t samples) {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
@ -475,7 +475,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD);
// now do the read // now do the read
DoAcquisition_config(true, 0); DoAcquisition_config(verbose, samples);
// Turn off antenna // Turn off antenna
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);

View file

@ -15,8 +15,7 @@
#include "pm3_cmd.h" // struct #include "pm3_cmd.h" // struct
void AcquireRawAdcSamples125k(int divisor); void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command, bool verbose, uint32_t samples);
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command);
void ReadTItag(void); void ReadTItag(void);
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);

View file

@ -329,7 +329,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
if (verbose) { if (verbose) {
if (checked == -1) { if (checked == -1) {
Dbprintf("lf sampling aborted"); Dbprintf("lf sampling aborted");
} else if (cancel_counter == cancel_after) { } else if ((cancel_counter == cancel_after) && (cancel_after > 0)){
Dbprintf("lf sampling cancelled after %u", cancel_counter); Dbprintf("lf sampling cancelled after %u", cancel_counter);
} }

View file

@ -2242,6 +2242,8 @@ void MifareCIdent(void) {
uint8_t rec[1] = {0x00}; uint8_t rec[1] = {0x00};
uint8_t recpar[1] = {0x00}; uint8_t recpar[1] = {0x00};
uint8_t rats[4] = { ISO14443A_CMD_RATS, 0x80, 0x31, 0x73 }; uint8_t rats[4] = { ISO14443A_CMD_RATS, 0x80, 0x31, 0x73 };
uint8_t rdbl[4] = { ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
uint8_t rdbl0[4] = { ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE); uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE); uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE);
uint8_t *uid = BigBuf_malloc(10); uint8_t *uid = BigBuf_malloc(10);
@ -2276,10 +2278,22 @@ void MifareCIdent(void) {
ReaderTransmit(rats, sizeof(rats), NULL); ReaderTransmit(rats, sizeof(rats), NULL);
res = ReaderReceive(buf, par); res = ReaderReceive(buf, par);
// test for some MFC gen2
if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10\xF0\x05", 11) == 0) { if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10\xF0\x05", 11) == 0) {
// super card ident
uint8_t super[] = {0x0A, 0x00, 0x00, 0xA6, 0xB0, 0x00, 0x10, 0x14, 0x1D};
ReaderTransmit(super, sizeof(super), NULL);
res = ReaderReceive(buf, par);
if (res == 22) {
isGen = MAGIC_SUPER;
goto OUT;
}
isGen = MAGIC_GEN_2; isGen = MAGIC_GEN_2;
goto OUT; goto OUT;
} }
// test for some MFC 7b gen2
if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) { if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
isGen = MAGIC_GEN_2; isGen = MAGIC_GEN_2;
} }
@ -2303,6 +2317,37 @@ void MifareCIdent(void) {
isGen = MAGIC_GEN_2; isGen = MAGIC_GEN_2;
goto OUT; goto OUT;
} }
// test for NTAG213 magic gen2
if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xA5\x00\x04\x04\x02\x01\x00\x0F\x03\x79\x0C", 18) == 0) {
isGen = MAGIC_GEN_2;
goto OUT;
}
// magic ntag test
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(40);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res == 2) {
ReaderTransmit(rdbl, sizeof(rdbl), NULL);
res = ReaderReceive(buf, par);
if (res == 18) {
isGen = MAGIC_NTAG21X;
}
}
// magic MFC Gen3 test
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(40);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res == 2) {
ReaderTransmit(rdbl0, sizeof(rdbl0), NULL);
res = ReaderReceive(buf, par);
if (res == 18) {
isGen = MAGIC_GEN_3;
}
}
}; };
OUT: OUT:
@ -2317,29 +2362,29 @@ OUT:
void MifareHasStaticNonce(void) { void MifareHasStaticNonce(void) {
// variables // variables
int retval = PM3_SUCCESS, len; int retval = PM3_SUCCESS;
uint32_t nt = 0;
uint32_t nt = 0 ;
uint8_t rec[1] = {0x00};
uint8_t recpar[1] = {0x00};
uint8_t *uid = BigBuf_malloc(10); uint8_t *uid = BigBuf_malloc(10);
uint8_t data[1] = {0x00}; uint8_t data[1] = { NONCE_FAIL };
struct Crypto1State mpcs = {0, 0}; struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs; struct Crypto1State *pcs;
pcs = &mpcs; pcs = &mpcs;
iso14a_card_select_t card_info;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
for (int i = 0; i < 3; i++) { uint8_t counter = 0;
for (uint8_t i = 0; i < 3; i++) {
iso14a_card_select_t card_info;
if (!iso14443a_select_card(uid, &card_info, NULL, true, 0, true)) { if (!iso14443a_select_card(uid, &card_info, NULL, true, 0, true)) {
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
} }
uint8_t rec[1] = {0x00};
uint8_t recpar[1] = {0x00};
// Transmit MIFARE_CLASSIC_AUTH 0x60, block 0 // Transmit MIFARE_CLASSIC_AUTH 0x60, block 0
len = mifare_sendcmd_short(pcs, false, MIFARE_AUTH_KEYA, 0, rec, recpar, NULL); int len = mifare_sendcmd_short(pcs, false, MIFARE_AUTH_KEYA, 0, rec, recpar, NULL);
if (len != 4) { if (len != 4) {
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
@ -2347,14 +2392,24 @@ void MifareHasStaticNonce(void) {
// Save the tag nonce (nt) // Save the tag nonce (nt)
if (nt == bytes_to_num(rec, 4)) { if (nt == bytes_to_num(rec, 4)) {
data[0]++; counter++;
} }
nt = bytes_to_num(rec, 4); nt = bytes_to_num(rec, 4);
// some cards with static nonce need to be reset before next query
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
CHK_TIMEOUT(); CHK_TIMEOUT();
} }
if (counter) {
Dbprintf("%u static nonce %08x", data[0], nt);
data[0] = NONCE_STATIC;
} else {
data[0] = NONCE_NORMAL;
}
OUT: OUT:
reply_ng(CMD_HF_MIFARE_STATIC_NONCE, retval, data, sizeof(data)); reply_ng(CMD_HF_MIFARE_STATIC_NONCE, retval, data, sizeof(data));
// turns off // turns off

View file

@ -118,6 +118,7 @@ void MifareDesfireGetInformation(void) {
struct p { struct p {
uint8_t isOK; uint8_t isOK;
uint8_t uid[7]; uint8_t uid[7];
uint8_t uidlen;
uint8_t versionHW[7]; uint8_t versionHW[7];
uint8_t versionSW[7]; uint8_t versionSW[7];
uint8_t details[14]; uint8_t details[14];
@ -148,15 +149,9 @@ void MifareDesfireGetInformation(void) {
return; return;
} }
if (card.uidlen != 7) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen);
payload.isOK = 2; // 2 == WRONG UID
reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload));
switch_off();
return;
}
// add uid. // add uid.
memcpy(payload.uid, card.uid, sizeof(payload.uid)); memcpy(payload.uid, card.uid, card.uidlen);
payload.uidlen = card.uidlen;
LED_A_ON(); LED_A_ON();
uint8_t cmd[] = {0x90, MFDES_GET_VERSION, 0x00, 0x00, 0x00}; uint8_t cmd[] = {0x90, MFDES_GET_VERSION, 0x00, 0x00, 0x00};

View file

@ -238,8 +238,10 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/cmdhfmfhard.c ${PM3_ROOT}/client/src/cmdhfmfhard.c
${PM3_ROOT}/client/src/cmdhfmfp.c ${PM3_ROOT}/client/src/cmdhfmfp.c
${PM3_ROOT}/client/src/cmdhfmfu.c ${PM3_ROOT}/client/src/cmdhfmfu.c
${PM3_ROOT}/client/src/cmdhfst.c
${PM3_ROOT}/client/src/cmdhfthinfilm.c ${PM3_ROOT}/client/src/cmdhfthinfilm.c
${PM3_ROOT}/client/src/cmdhftopaz.c ${PM3_ROOT}/client/src/cmdhftopaz.c
${PM3_ROOT}/client/src/cmdhfwaveshare.c
${PM3_ROOT}/client/src/cmdhw.c ${PM3_ROOT}/client/src/cmdhw.c
${PM3_ROOT}/client/src/cmdlf.c ${PM3_ROOT}/client/src/cmdlf.c
${PM3_ROOT}/client/src/cmdlfawid.c ${PM3_ROOT}/client/src/cmdlfawid.c

View file

@ -432,8 +432,10 @@ SRCS = aidsearch.c \
cmdhfmfhard.c \ cmdhfmfhard.c \
cmdhfmfu.c \ cmdhfmfu.c \
cmdhfmfp.c \ cmdhfmfp.c \
cmdhfst.c \
cmdhfthinfilm.c \ cmdhfthinfilm.c \
cmdhftopaz.c \ cmdhftopaz.c \
cmdhfwaveshare.c \
cmdhw.c \ cmdhw.c \
cmdlf.c \ cmdlf.c \
cmdlfawid.c \ cmdlfawid.c \

View file

@ -117,8 +117,10 @@ add_library(pm3rrg_rdv4 SHARED
${PM3_ROOT}/client/src/cmdhfmfhard.c ${PM3_ROOT}/client/src/cmdhfmfhard.c
${PM3_ROOT}/client/src/cmdhfmfp.c ${PM3_ROOT}/client/src/cmdhfmfp.c
${PM3_ROOT}/client/src/cmdhfmfu.c ${PM3_ROOT}/client/src/cmdhfmfu.c
${PM3_ROOT}/client/src/cmdhfst.c
${PM3_ROOT}/client/src/cmdhfthinfilm.c ${PM3_ROOT}/client/src/cmdhfthinfilm.c
${PM3_ROOT}/client/src/cmdhftopaz.c ${PM3_ROOT}/client/src/cmdhftopaz.c
${PM3_ROOT}/client/src/cmdhfwaveshare.c
${PM3_ROOT}/client/src/cmdhw.c ${PM3_ROOT}/client/src/cmdhw.c
${PM3_ROOT}/client/src/cmdlf.c ${PM3_ROOT}/client/src/cmdlf.c
${PM3_ROOT}/client/src/cmdlfawid.c ${PM3_ROOT}/client/src/cmdlfawid.c

View file

@ -191,7 +191,7 @@ local function read_config()
end end
print('Magic NTAG 21* Configuration') print('Magic NTAG 21* Configuration')
print(' - Type ', typestr, '(geniune cardtype)') print(' - Type ', typestr, '(genuine cardtype)')
print(' - Password', pwd) print(' - Password', pwd)
print(' - Pack ', pack) print(' - Pack ', pack)
print(' - Version ', version) print(' - Version ', version)

View file

@ -35,6 +35,8 @@
#include "cmdhfthinfilm.h" // Thinfilm #include "cmdhfthinfilm.h" // Thinfilm
#include "cmdhflto.h" // LTO-CM #include "cmdhflto.h" // LTO-CM
#include "cmdhfcryptorf.h" // CryptoRF #include "cmdhfcryptorf.h" // CryptoRF
#include "cmdhfst.h" // ST rothult
#include "cmdhfwaveshare.h" // Waveshare
#include "cmdtrace.h" // trace list #include "cmdtrace.h" // trace list
#include "ui.h" #include "ui.h"
#include "proxgui.h" #include "proxgui.h"
@ -84,8 +86,6 @@ static int usage_hf_tune(void) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
#define PROMPT_CLEARLINE PrintAndLogEx(INPLACE, " \r")
int CmdHFSearch(const char *Cmd) { int CmdHFSearch(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
@ -365,8 +365,10 @@ static command_t CommandTable[] = {
{"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"}, {"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"},
{"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"}, {"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"},
{"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"}, {"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"},
{"st", CmdHF_ST, AlwaysAvailable, "{ ST Rothult RFIDs... }"},
{"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"}, {"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"},
{"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"}, {"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
{"waveshare", CmdHFWaveshare, AlwaysAvailable, "{ Waveshare NFC ePaper... }"},
{"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"}, {"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"},
{"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"},

View file

@ -31,7 +31,7 @@
bool APDUInFramingEnable = true; bool APDUInFramingEnable = true;
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static int waitCmd(uint8_t iSelect); static int waitCmd(uint8_t iSelect, uint32_t timeout);
static const manufactureName manufactureMapping[] = { static const manufactureName manufactureMapping[] = {
// ID, "Vendor Country" // ID, "Vendor Country"
@ -170,19 +170,40 @@ uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
static int usage_hf_14a_config(void) { static int usage_hf_14a_config(void) {
PrintAndLogEx(NORMAL, "Usage: hf 14a config [a 0|1|2] [b 0|1|2] [2 0|1|2] [3 0|1|2]"); PrintAndLogEx(NORMAL, "Usage: hf 14a config [a 0|1|2] [b 0|1|2] [2 0|1|2] [3 0|1|2]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "\nOptions:");
PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " a 0|1|2 ATQA<>anticollision: 0=follow standard 1=execute anticol 2=skip anticol"); PrintAndLogEx(NORMAL, " a 0|1|2 ATQA<>anticollision: 0=follow standard 1=execute anticol 2=skip anticol");
PrintAndLogEx(NORMAL, " b 0|1|2 BCC: 0=follow standard 1=use fixed BCC 2=use card BCC"); PrintAndLogEx(NORMAL, " b 0|1|2 BCC: 0=follow standard 1=use fixed BCC 2=use card BCC");
PrintAndLogEx(NORMAL, " 2 0|1|2 SAK<>CL2: 0=follow standard 1=execute CL2 2=skip CL2"); PrintAndLogEx(NORMAL, " 2 0|1|2 SAK<>CL2: 0=follow standard 1=execute CL2 2=skip CL2");
PrintAndLogEx(NORMAL, " 3 0|1|2 SAK<>CL3: 0=follow standard 1=execute CL3 2=skip CL3"); PrintAndLogEx(NORMAL, " 3 0|1|2 SAK<>CL3: 0=follow standard 1=execute CL3 2=skip CL3");
PrintAndLogEx(NORMAL, " r 0|1|2 SAK<>ATS: 0=follow standard 1=execute RATS 2=skip RATS"); PrintAndLogEx(NORMAL, " r 0|1|2 SAK<>ATS: 0=follow standard 1=execute RATS 2=skip RATS");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "\nExamples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config ")" Print current configuration"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config ")" Print current configuration");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 ")" Force execution of anticollision"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 ")" Force execution of anticollision");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 ")" Restore ATQA interpretation"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 ")" Restore ATQA interpretation");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 1 ")" Force fix of bad BCC in anticollision"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 1 ")" Force fix of bad BCC in anticollision");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 0 ")" Restore BCC check"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 0 ")" Restore BCC check");
PrintAndLogEx(NORMAL, "\nExamples to revive Gen2/DirectWrite magic cards failing at anticollision:");
PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 4b UID")":");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 b 2 2 2 r 2"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 b 0 2 0 r 0"));
PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 4b UID")":");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 b 2 2 2 r 2"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344441802006263646566676869"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 b 0 2 0 r 0"));
PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 7b UID")":");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 b 2 2 1 3 2 r 2"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566084400626364656667"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 b 0 2 0 3 0 r 0"));
PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 7b UID")":");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 b 2 2 1 3 2 r 2"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566184200626364656667"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 b 0 2 0 3 0 r 0"));
PrintAndLogEx(NORMAL, _CYAN_(" MFUL ")"/" _CYAN_(" MFUL EV1 ")"/" _CYAN_(" MFULC")":");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 b 2 2 1 3 2 r 2"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid 04112233445566"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 b 0 2 0 3 0 r 0"));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -201,6 +222,7 @@ static int usage_hf_14a_sim(void) {
PrintAndLogEx(NORMAL, " 7 = AMIIBO (NTAG 215), pack 0x8080"); PrintAndLogEx(NORMAL, " 7 = AMIIBO (NTAG 215), pack 0x8080");
PrintAndLogEx(NORMAL, " 8 = MIFARE Classic 4k"); PrintAndLogEx(NORMAL, " 8 = MIFARE Classic 4k");
PrintAndLogEx(NORMAL, " 9 = FM11RF005SH Shanghai Metro"); PrintAndLogEx(NORMAL, " 9 = FM11RF005SH Shanghai Metro");
PrintAndLogEx(NORMAL, " 10 = JCOP 31/41 Rothult");
// PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID"); // PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID");
PrintAndLogEx(NORMAL, " u : 4, 7 byte UID"); PrintAndLogEx(NORMAL, " u : 4, 7 byte UID");
PrintAndLogEx(NORMAL, " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader"); PrintAndLogEx(NORMAL, " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader");
@ -1308,17 +1330,17 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
if (reply) { if (reply) {
int res = 0; int res = 0;
if (active_select) if (active_select)
res = waitCmd(1); res = waitCmd(1, timeout);
if (!res && datalen > 0) if (!res && datalen > 0)
waitCmd(0); waitCmd(0, timeout);
} }
return 0; return 0;
} }
static int waitCmd(uint8_t iSelect) { static int waitCmd(uint8_t iSelect, uint32_t timeout) {
PacketResponseNG resp; PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { if (WaitForResponseTimeout(CMD_ACK, &resp, timeout + 1500)) {
uint16_t len = (resp.oldarg[0] & 0xFFFF); uint16_t len = (resp.oldarg[0] & 0xFFFF);
if (iSelect) { if (iSelect) {
len = (resp.oldarg[1] & 0xFFFF); len = (resp.oldarg[1] & 0xFFFF);
@ -1663,6 +1685,12 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
} }
getTagLabel(card.uid[0], card.uid[1]); getTagLabel(card.uid[0], card.uid[1]);
break; break;
case 0x57: // Qualcomm
if (memcmp(card.uid, "WSDZ10m", 7) == 0) {
isMifareClassic = false;
printTag("Waveshare NFC-Powered e-Paper");
}
break;
default: default:
getTagLabel(card.uid[0], card.uid[1]); getTagLabel(card.uid[0], card.uid[1]);
switch (card.sak) { switch (card.sak) {
@ -1955,23 +1983,28 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
isMagic = detect_classic_magic(); isMagic = detect_classic_magic();
if (isMifareClassic) { if (isMifareClassic) {
int res = detect_classic_prng();
if (res == 1)
PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_("weak"));
else if (res == 0)
PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_("hard"));
else
PrintAndLogEx(FAILED, "Prng detection: " _RED_("fail"));
if (do_nack_test) int res = detect_classic_static_nonce();
detect_classic_nackbug(false); if (res == NONCE_STATIC)
res = detect_classic_static_nonce();
if (res == 1)
PrintAndLogEx(SUCCESS, "Static nonce: " _YELLOW_("yes")); PrintAndLogEx(SUCCESS, "Static nonce: " _YELLOW_("yes"));
if (res == 2 && verbose)
PrintAndLogEx(SUCCESS, "Static nonce: " _RED_("fail"));
if (res == NONCE_FAIL && verbose)
PrintAndLogEx(SUCCESS, "Static nonce: " _RED_("read failed"));
if (res == NONCE_NORMAL) {
// not static
res = detect_classic_prng();
if (res == 1)
PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_("weak"));
else if (res == 0)
PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_("hard"));
else
PrintAndLogEx(FAILED, "Prng detection: " _RED_("fail"));
if (do_nack_test)
detect_classic_nackbug(false);
}
} }
} }

View file

@ -381,6 +381,7 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
{"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"}, {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"}, {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
{"MICRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"}, {"MICRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"},
{"Spark1 Public key", "04d64bb732c0d214e7ec580736acf847284b502c25c0f7f2fa86aace1dada4387a"},
}; };
/* /*
uint8_t nxp_15693_public_keys[][PUBLIC_ECDA_KEYLEN] = { uint8_t nxp_15693_public_keys[][PUBLIC_ECDA_KEYLEN] = {

View file

@ -442,13 +442,19 @@ void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
uint8_t block = 0; uint8_t block = 0;
if (cmdsize == 13) if (cmdsize == 13)
block = cmd[10]; block = cmd[10];
else if (cmdsize == 5)
block = cmd[2];
snprintf(exp, size, "READBLOCK(%d)", block); snprintf(exp, size, "READBLOCK(%d)", block);
return; return;
} }
case ISO15693_WRITEBLOCK: case ISO15693_WRITEBLOCK: {
snprintf(exp, size, "WRITEBLOCK"); uint8_t block = 0;
if (cmdsize == 9)
block = cmd[2];
snprintf(exp, size, "WRITEBLOCK(%d)", block);
return; return;
}
case ISO15693_LOCKBLOCK: case ISO15693_LOCKBLOCK:
snprintf(exp, size, "LOCKBLOCK"); snprintf(exp, size, "LOCKBLOCK");
return; return;

View file

@ -512,7 +512,7 @@ static int usage_hf14_gen3uid(void) {
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3uid 01020304050607")); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3uid 01020304050607"));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_hf14_gen3blk(void) { static int usage_hf14_gen3block(void) {
PrintAndLogEx(NORMAL, "Overwrite full manufacturer block for magic GEN 3 card"); PrintAndLogEx(NORMAL, "Overwrite full manufacturer block for magic GEN 3 card");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: hf mf gen3blk [h] [block data (up to 32 hex symbols)]"); PrintAndLogEx(NORMAL, "Usage: hf mf gen3blk [h] [block data (up to 32 hex symbols)]");
@ -531,15 +531,15 @@ static int usage_hf14_gen3blk(void) {
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3blk")); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3blk"));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_hf14_gen3freez(void) { static int usage_hf14_gen3freeze(void) {
PrintAndLogEx(NORMAL, "Lock further UID changes. No more UID changes available after operation completed"); PrintAndLogEx(NORMAL, "Perma lock further UID changes. No more UID changes available after operation completed");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: hf mf gen3freez [h] <Y>"); PrintAndLogEx(NORMAL, "Usage: hf mf gen3freeze [h] <y>");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " <Y> confirm UID locks operation"); PrintAndLogEx(NORMAL, " <y> confirm UID locks operation");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3freez Y")); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3freeze y"));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -996,6 +996,8 @@ static int CmdHF14AMfDump(const char *Cmd) {
return PM3_EFILE; return PM3_EFILE;
} }
PrintAndLogEx(INFO, "Using `" _YELLOW_("%s") "`", keyFilename);
// Read keys A from file // Read keys A from file
size_t bytes_read; size_t bytes_read;
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
@ -1026,6 +1028,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
for (tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) { for (tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) {
PrintAndLogEx(NORMAL, "." NOLF); PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
payload.blockno = FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1; payload.blockno = FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1;
payload.keytype = 0; payload.keytype = 0;
@ -1357,7 +1360,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
} }
// check if tag doesn't have static nonce // check if tag doesn't have static nonce
if (detect_classic_static_nonce() == 1) { if (detect_classic_static_nonce() == NONCE_STATIC) {
PrintAndLogEx(WARNING, "Static nonce detected. Quitting..."); PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf staticnested`")); PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf staticnested`"));
return PM3_EOPABORTED; return PM3_EOPABORTED;
@ -1607,8 +1610,8 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) {
} }
// check if tag have static nonce // check if tag have static nonce
if (detect_classic_static_nonce() == 0) { if (detect_classic_static_nonce() != NONCE_STATIC) {
PrintAndLogEx(WARNING, "None static nonce detected. Quitting..."); PrintAndLogEx(WARNING, "Normal nonce detected, or failed read of card. Quitting...");
PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf nested`")); PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf nested`"));
return PM3_EOPABORTED; return PM3_EOPABORTED;
} }
@ -1921,7 +1924,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
if (!know_target_key && nonce_file_read == false) { if (!know_target_key && nonce_file_read == false) {
// check if tag doesn't have static nonce // check if tag doesn't have static nonce
if (detect_classic_static_nonce() == 1) { if (detect_classic_static_nonce() == NONCE_STATIC) {
PrintAndLogEx(WARNING, "Static nonce detected. Quitting..."); PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
PrintAndLogEx(HINT, "\tTry use `" _YELLOW_("hf mf staticnested") "`"); PrintAndLogEx(HINT, "\tTry use `" _YELLOW_("hf mf staticnested") "`");
return PM3_EOPABORTED; return PM3_EOPABORTED;
@ -2002,7 +2005,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
bool slow = false; bool slow = false;
bool legacy_mfchk = false; bool legacy_mfchk = false;
int prng_type = PM3_EUNDEF; int prng_type = PM3_EUNDEF;
int has_staticnonce = 2; int has_staticnonce;
bool verbose = false; bool verbose = false;
bool has_filename = false; bool has_filename = false;
bool errors = false; bool errors = false;
@ -2120,17 +2123,20 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
// read uid to generate a filename for the key file // read uid to generate a filename for the key file
char *fptr = GenerateFilename("hf-mf-", "-key.bin"); char *fptr = GenerateFilename("hf-mf-", "-key.bin");
// card prng type (weak=1 / hard=0 / select/card comm error = negative value)
prng_type = detect_classic_prng();
if (prng_type < 0) {
PrintAndLogEx(FAILED, "\nNo tag detected or other tag communication error");
free(e_sector);
return prng_type;
}
// check if tag doesn't have static nonce // check if tag doesn't have static nonce
has_staticnonce = detect_classic_static_nonce(); has_staticnonce = detect_classic_static_nonce();
// card prng type (weak=1 / hard=0 / select/card comm error = negative value)
if (has_staticnonce == NONCE_NORMAL) {
prng_type = detect_classic_prng();
if (prng_type < 0) {
PrintAndLogEx(FAILED, "\nNo tag detected or other tag communication error");
free(e_sector);
return prng_type;
}
}
// print parameters // print parameters
if (verbose) { if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("SETTINGS") " ======================="); PrintAndLogEx(INFO, "======================= " _YELLOW_("SETTINGS") " =======================");
@ -2140,10 +2146,12 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), keyType ? 'B' : 'A'); PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), keyType ? 'B' : 'A');
PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex(key, sizeof(key))); PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex(key, sizeof(key)));
if (has_staticnonce) if (has_staticnonce == NONCE_STATIC)
PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("%s & STATIC"), prng_type ? "WEAK" : "HARD"); PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("STATIC"));
else else if (has_staticnonce == NONCE_NORMAL)
PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("%s"), prng_type ? "WEAK" : "HARD"); PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("%s"), prng_type ? "WEAK" : "HARD");
else
PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("Could not determine PRNG,") " " _RED_("read failed."));
PrintAndLogEx(INFO, " dictionary .... " _YELLOW_("%s"), strlen(filename) ? filename : "NONE"); PrintAndLogEx(INFO, " dictionary .... " _YELLOW_("%s"), strlen(filename) ? filename : "NONE");
PrintAndLogEx(INFO, " legacy mode ... " _YELLOW_("%s"), legacy_mfchk ? "True" : "False"); PrintAndLogEx(INFO, " legacy mode ... " _YELLOW_("%s"), legacy_mfchk ? "True" : "False");
@ -2163,7 +2171,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
} }
if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) == PM3_SUCCESS) { if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) == PM3_SUCCESS) {
PrintAndLogEx(INFO, "target sector:%3u key type: %c -- using valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", PrintAndLogEx(INFO, "target sector:%3u key type: %c -- using valid key [ " _GREEN_("%s") "] (used for nested / hardnested attack)",
blockNo, blockNo,
keyType ? 'B' : 'A', keyType ? 'B' : 'A',
sprint_hex(key, sizeof(key)) sprint_hex(key, sizeof(key))
@ -2198,13 +2206,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
know_target_key = true; know_target_key = true;
blockNo = i; blockNo = i;
keyType = j; keyType = j;
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key ["_YELLOW_("%s") "] (used for nested / hardnested attack)", PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "] (used for nested / hardnested attack)",
i, i,
j ? 'B' : 'A', j ? 'B' : 'A',
sprint_hex(key, sizeof(key)) sprint_hex(key, sizeof(key))
); );
} else { } else {
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key ["_YELLOW_("%s") "]", PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]",
i, i,
j ? 'B' : 'A', j ? 'B' : 'A',
sprint_hex(key, sizeof(key)) sprint_hex(key, sizeof(key))
@ -2216,10 +2224,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
} }
} }
if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("STOP KNOWN KEY ATTACK") " =======================");
}
if (num_found_keys == sectors_cnt * 2) { if (num_found_keys == sectors_cnt * 2) {
goto all_found; goto all_found;
} }
@ -2263,6 +2267,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
if (e_sector[i].foundKey[j] == 0) { if (e_sector[i].foundKey[j] == 0) {
for (uint32_t k = 0; k < key_cnt; k++) { for (uint32_t k = 0; k < key_cnt; k++) {
PrintAndLogEx(NORMAL, "." NOLF); PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, (keyBlock + (6 * k)), &key64) == PM3_SUCCESS) { if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, (keyBlock + (6 * k)), &key64) == PM3_SUCCESS) {
e_sector[i].Key[j] = bytes_to_num((keyBlock + (6 * k)), 6); e_sector[i].Key[j] = bytes_to_num((keyBlock + (6 * k)), 6);
@ -2310,8 +2315,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
lastChunk = false; lastChunk = false;
} // end strategy } // end strategy
} }
if (verbose) PrintAndLogEx(INFO, "======================= " _YELLOW_("STOP DICTIONARY ATTACK") " =======================");
// Analyse the dictionary attack // Analyse the dictionary attack
for (int i = 0; i < sectors_cnt; i++) { for (int i = 0; i < sectors_cnt; i++) {
@ -2326,13 +2329,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
know_target_key = true; know_target_key = true;
blockNo = i; blockNo = i;
keyType = j; keyType = j;
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "] (used for nested / hardnested attack)",
i, i,
j ? 'B' : 'A', j ? 'B' : 'A',
sprint_hex(tmp_key, sizeof(tmp_key)) sprint_hex(tmp_key, sizeof(tmp_key))
); );
} else { } else {
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]",
i, i,
j ? 'B' : 'A', j ? 'B' : 'A',
sprint_hex(tmp_key, sizeof(tmp_key)) sprint_hex(tmp_key, sizeof(tmp_key))
@ -2345,17 +2348,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
// Check if at least one sector key was found // Check if at least one sector key was found
if (know_target_key == false) { if (know_target_key == false) {
// Check if the darkside attack can be used // Check if the darkside attack can be used
if (prng_type && has_staticnonce == false) { if (prng_type && has_staticnonce != NONCE_STATIC) {
if (verbose) { if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("START DARKSIDE ATTACK") " ======================="); PrintAndLogEx(INFO, "======================= " _YELLOW_("START DARKSIDE ATTACK") " =======================");
} }
isOK = mfDarkside(FirstBlockOfSector(blockNo), keyType, &key64); isOK = mfDarkside(FirstBlockOfSector(blockNo), keyType, &key64);
if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("STOP DARKSIDE ATTACK") " =======================");
}
switch (isOK) { switch (isOK) {
case -1 : case -1 :
PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); PrintAndLogEx(WARNING, "\nButton pressed. Aborted.");
@ -2381,7 +2380,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
// Store the keys // Store the keys
e_sector[blockNo].Key[keyType] = key64; e_sector[blockNo].Key[keyType] = key64;
e_sector[blockNo].foundKey[keyType] = 'S'; e_sector[blockNo].foundKey[keyType] = 'S';
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)", PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "] (used for nested / hardnested attack)",
blockNo, blockNo,
keyType ? 'B' : 'A', keyType ? 'B' : 'A',
sprint_hex(key, sizeof(key)) sprint_hex(key, sizeof(key))
@ -2421,7 +2420,7 @@ noValidKeyFound:
if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) { if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) {
e_sector[i].Key[j] = bytes_to_num(tmp_key, 6); e_sector[i].Key[j] = bytes_to_num(tmp_key, 6);
e_sector[i].foundKey[j] = 'R'; e_sector[i].foundKey[j] = 'R';
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]",
i, i,
j ? 'B' : 'A', j ? 'B' : 'A',
sprint_hex(tmp_key, sizeof(tmp_key)) sprint_hex(tmp_key, sizeof(tmp_key))
@ -2463,7 +2462,7 @@ noValidKeyFound:
e_sector[current_sector_i].foundKey[current_key_type_i] = 'A'; e_sector[current_sector_i].foundKey[current_key_type_i] = 'A';
e_sector[current_sector_i].Key[current_key_type_i] = key64; e_sector[current_sector_i].Key[current_key_type_i] = key64;
num_to_bytes(key64, 6, tmp_key); num_to_bytes(key64, 6, tmp_key);
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]",
current_sector_i, current_sector_i,
current_key_type_i ? 'B' : 'A', current_key_type_i ? 'B' : 'A',
sprint_hex(tmp_key, sizeof(tmp_key)) sprint_hex(tmp_key, sizeof(tmp_key))
@ -2479,9 +2478,6 @@ noValidKeyFound:
} }
} }
if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("STOP READ B KEY ATTACK") " =======================");
}
} }
} }
@ -2489,7 +2485,7 @@ noValidKeyFound:
skipReadBKey: skipReadBKey:
if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) { if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) {
if (has_staticnonce) if (has_staticnonce == NONCE_STATIC)
goto tryStaticnested; goto tryStaticnested;
if (prng_type && (nested_failed == false)) { if (prng_type && (nested_failed == false)) {
@ -2545,9 +2541,6 @@ tryNested:
return PM3_ESOFT; return PM3_ESOFT;
} }
} }
if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("STOP NESTED ATTACK") " =======================");
}
} else { } else {
tryHardnested: // If the nested attack fails then we try the hardnested attack tryHardnested: // If the nested attack fails then we try the hardnested attack
@ -2583,13 +2576,9 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
num_to_bytes(foundkey, 6, tmp_key); num_to_bytes(foundkey, 6, tmp_key);
e_sector[current_sector_i].Key[current_key_type_i] = foundkey; e_sector[current_sector_i].Key[current_key_type_i] = foundkey;
e_sector[current_sector_i].foundKey[current_key_type_i] = 'H'; e_sector[current_sector_i].foundKey[current_key_type_i] = 'H';
if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("STOP HARDNESTED ATTACK") " =======================");
}
} }
if (has_staticnonce) { if (has_staticnonce == NONCE_STATIC) {
tryStaticnested: tryStaticnested:
if (verbose) { if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("START STATIC NESTED ATTACK") " ======================="); PrintAndLogEx(INFO, "======================= " _YELLOW_("START STATIC NESTED ATTACK") " =======================");
@ -2620,15 +2609,11 @@ tryStaticnested:
break; break;
} }
} }
if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("STOP STATIC NESTED ATTACK") " =======================");
}
} }
// Check if the key was found // Check if the key was found
if (e_sector[current_sector_i].foundKey[current_key_type_i]) { if (e_sector[current_sector_i].foundKey[current_key_type_i]) {
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]", PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]",
current_sector_i, current_sector_i,
current_key_type_i ? 'B' : 'A', current_key_type_i ? 'B' : 'A',
sprint_hex(tmp_key, sizeof(tmp_key)) sprint_hex(tmp_key, sizeof(tmp_key))
@ -3183,6 +3168,7 @@ static int CmdHF14AMfChk(const char *Cmd) {
for (uint16_t c = 0; c < keycnt; c += max_keys) { for (uint16_t c = 0; c < keycnt; c += max_keys) {
PrintAndLogEx(NORMAL, "." NOLF); PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
if (kbd_enter_pressed()) { if (kbd_enter_pressed()) {
PrintAndLogEx(INFO, "\naborted via keyboard!\n"); PrintAndLogEx(INFO, "\naborted via keyboard!\n");
@ -3761,6 +3747,7 @@ int CmdHF14AMfELoad(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
PrintAndLogEx(NORMAL, "." NOLF); PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
blockNum++; blockNum++;
counter += blockWidth; counter += blockWidth;
@ -4186,6 +4173,7 @@ static int CmdHF14AMfCLoad(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
PrintAndLogEx(NORMAL, "." NOLF); PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
} }
PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "\n");
return PM3_SUCCESS; return PM3_SUCCESS;
@ -4448,6 +4436,7 @@ static int CmdHF14AMfCSave(const char *Cmd) {
PrintAndLogEx(WARNING, "Cant set emul block: %d", i); PrintAndLogEx(WARNING, "Cant set emul block: %d", i);
} }
PrintAndLogEx(NORMAL, "." NOLF); PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
} }
PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "\n");
PrintAndLogEx(SUCCESS, "uploaded %d bytes to emulator memory", bytes); PrintAndLogEx(SUCCESS, "uploaded %d bytes to emulator memory", bytes);
@ -4536,7 +4525,7 @@ static int CmdHF14AMfCView(const char *Cmd) {
free(dump); free(dump);
return PM3_ESOFT; return PM3_ESOFT;
} }
PrintAndLogEx(NORMAL, "." NOLF); PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout); fflush(stdout);
} }
@ -5170,18 +5159,18 @@ static int CmdHf14AGen3UID(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdHf14AGen3Blk(const char *Cmd) { static int CmdHf14AGen3Block(const char *Cmd) {
uint8_t block[16] = {0x00}; uint8_t block[16] = {0x00};
int blocklen = 0; int blocklen = 0;
uint8_t newBlock[16] = {0x00}; uint8_t newBlock[16] = {0x00};
char ctmp = tolower(param_getchar(Cmd, 0)); char ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_hf14_gen3blk(); if (ctmp == 'h') return usage_hf14_gen3block();
if (ctmp != '\0' && param_gethex_to_eol(Cmd, 0, block, sizeof(block), &blocklen)) if (ctmp != '\0' && param_gethex_to_eol(Cmd, 0, block, sizeof(block), &blocklen))
return usage_hf14_gen3blk(); return usage_hf14_gen3block();
int res = mfGen3Blk(block, blocklen, newBlock); int res = mfGen3Block(block, blocklen, newBlock);
if (res) { if (res) {
PrintAndLogEx(ERR, "Can't change manufacturer block data. Error=%d", res); PrintAndLogEx(ERR, "Can't change manufacturer block data. Error=%d", res);
return PM3_ESOFT; return PM3_ESOFT;
@ -5191,18 +5180,17 @@ static int CmdHf14AGen3Blk(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdHf14AGen3Freez(const char *Cmd) { static int CmdHf14AGen3Freeze(const char *Cmd) {
char ctmp = param_getchar(Cmd, 0); char ctmp = tolower(param_getchar(Cmd, 0));
if (tolower(ctmp) == 'h') return usage_hf14_gen3freez(); if (ctmp == 'h') return usage_hf14_gen3freeze();
if (ctmp != 'Y') return usage_hf14_gen3freez(); if (ctmp != 'y') return usage_hf14_gen3freeze();
int res = mfGen3Freez(); int res = mfGen3Freeze();
if (res) { if (res) {
PrintAndLogEx(ERR, "Can't lock UID changes. Error=%d", res); PrintAndLogEx(ERR, "Can't lock UID changes. Error=%d", res);
return PM3_ESOFT; return PM3_ESOFT;
} }
PrintAndLogEx(SUCCESS, "MFC Gen3 UID permalocked");
PrintAndLogEx(SUCCESS, "Gen 3 UID locked");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -5243,18 +5231,18 @@ static command_t CommandTable[] = {
{"ecfill", CmdHF14AMfECFill, IfPm3Iso14443a, "Fill simulator memory with help of keys from simulator"}, {"ecfill", CmdHF14AMfECFill, IfPm3Iso14443a, "Fill simulator memory with help of keys from simulator"},
{"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from simulator memory"}, {"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from simulator memory"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic") " -----------------------"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic") " -----------------------"},
{"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID (magic chinese card)"}, {"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID"},
{"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"}, {"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"},
{"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block (magic chinese card)"}, {"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block"},
{"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block (magic chinese card)"}, {"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block"},
{"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector (magic chinese card)"}, {"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector"},
{"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump (magic chinese card)"}, {"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump"},
{"csave", CmdHF14AMfCSave, IfPm3Iso14443a, "Save dump from magic chinese card into file or emulator"}, {"csave", CmdHF14AMfCSave, IfPm3Iso14443a, "Save dump from card into file or emulator"},
{"cview", CmdHF14AMfCView, IfPm3Iso14443a, "view card"}, {"cview", CmdHF14AMfCView, IfPm3Iso14443a, "view card"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3") " -----------------------"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3") " -----------------------"},
{"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without manufacturer block (magic gen3 card)"}, {"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without manufacturer block"},
{"gen3blk", CmdHf14AGen3Blk, IfPm3Iso14443a, "Overwrite full manufacturer block (magic gen 3 card)"}, {"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite full manufacturer block"},
{"gen3freez", CmdHf14AGen3Freez, IfPm3Iso14443a, "Lock further UID changes (magic gen 3 card)"}, {"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock further UID changes"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"},
{"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},

View file

@ -1152,7 +1152,7 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n
} }
// --- GET SIGNATURE // --- GET SIGNATURE
static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len, nxp_cardtype_t card_type) { static int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, size_t signature_len, nxp_cardtype_t card_type) {
(void)card_type; (void)card_type;
if (uid == NULL) { if (uid == NULL) {
@ -1185,7 +1185,7 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign
uint8_t key[PUBLIC_DESFIRE_ECDA_KEYLEN]; uint8_t key[PUBLIC_DESFIRE_ECDA_KEYLEN];
param_gethex_to_eol(nxp_desfire_public_keys[i].value, 0, key, PUBLIC_DESFIRE_ECDA_KEYLEN, &dl); param_gethex_to_eol(nxp_desfire_public_keys[i].value, 0, key, PUBLIC_DESFIRE_ECDA_KEYLEN, &dl);
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, key, uid, 7, signature, signature_len, false); int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, key, uid, uidlen, signature, signature_len, false);
is_valid = (res == 0); is_valid = (res == 0);
if (is_valid) if (is_valid)
break; break;
@ -3228,7 +3228,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
SendCommandNG(CMD_HF_DESFIRE_INFO, NULL, 0); SendCommandNG(CMD_HF_DESFIRE_INFO, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_HF_DESFIRE_INFO, &resp, 1500)) { if (WaitForResponseTimeout(CMD_HF_DESFIRE_INFO, &resp, 1500) == false) {
PrintAndLogEx(WARNING, "Command execute timeout"); PrintAndLogEx(WARNING, "Command execute timeout");
DropField(); DropField();
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
@ -3237,6 +3237,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
struct p { struct p {
uint8_t isOK; uint8_t isOK;
uint8_t uid[7]; uint8_t uid[7];
uint8_t uidlen;
uint8_t versionHW[7]; uint8_t versionHW[7];
uint8_t versionSW[7]; uint8_t versionSW[7];
uint8_t details[14]; uint8_t details[14];
@ -3269,7 +3270,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------");
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(package->uid, sizeof(package->uid))); PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(package->uid, package->uidlen));
PrintAndLogEx(SUCCESS, " Batch number: " _GREEN_("%s"), sprint_hex(package->details + 7, 5)); PrintAndLogEx(SUCCESS, " Batch number: " _GREEN_("%s"), sprint_hex(package->details + 7, 5));
PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), package->details[12], package->details[13]); PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), package->details[12], package->details[13]);
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
@ -3319,7 +3320,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
if (handler_desfire_signature(signature, &signature_len) == PM3_SUCCESS) { if (handler_desfire_signature(signature, &signature_len) == PM3_SUCCESS) {
desfire_print_signature(package->uid, signature, signature_len, cardtype); desfire_print_signature(package->uid, package->uidlen, signature, signature_len, cardtype);
} else { } else {
PrintAndLogEx(WARNING, "--- Card doesn't support GetSignature cmd"); PrintAndLogEx(WARNING, "--- Card doesn't support GetSignature cmd");
} }

View file

@ -2540,6 +2540,7 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) {
return PM3_EINVARG; return PM3_EINVARG;
} }
PrintAndLogEx(INFO, "Please ignore possible transient BCC warnings");
// read block2. // read block2.
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFAREU_READBL, 2, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_MIFAREU_READBL, 2, 0, 0, NULL, 0);
@ -2552,6 +2553,21 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) {
uint8_t oldblock2[4] = {0x00}; uint8_t oldblock2[4] = {0x00};
memcpy(resp.data.asBytes, oldblock2, 4); memcpy(resp.data.asBytes, oldblock2, 4);
// Enforce bad BCC handling temporarily as BCC will be wrong between
// block 1 write and block2 write
hf14a_config config;
SendCommandNG(CMD_HF_ISO14443A_GET_CONFIG, NULL, 0);
if (!WaitForResponseTimeout(CMD_HF_ISO14443A_GET_CONFIG, &resp, 2000)) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
memcpy(&config, resp.data.asBytes, sizeof(hf14a_config));
int8_t oldconfig_bcc = config.forcebcc;
if (oldconfig_bcc != 2) {
config.forcebcc = 2;
SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG, (uint8_t *)&config, sizeof(hf14a_config));
}
// block 0. // block 0.
uint8_t data[4]; uint8_t data[4];
data[0] = uid[0]; data[0] = uid[0];
@ -2588,6 +2604,12 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) {
PrintAndLogEx(WARNING, "Command execute timeout"); PrintAndLogEx(WARNING, "Command execute timeout");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
// restore BCC config
if (oldconfig_bcc != 2) {
config.forcebcc = oldconfig_bcc;
SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG, (uint8_t *)&config, sizeof(hf14a_config));
}
return PM3_SUCCESS; return PM3_SUCCESS;
} }

470
client/src/cmdhfst.c Normal file
View file

@ -0,0 +1,470 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2020 iceman1001
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// High frequency ISO14443A / ST commands
//-----------------------------------------------------------------------------
#include "cmdhfst.h"
#include <ctype.h>
#include "fileutils.h"
#include "cmdparser.h" // command_t
#include "comms.h" // clearCommandBuffer
#include "cmdtrace.h"
#include "crc16.h"
#include "cmdhf14a.h"
#include "protocols.h" // definitions of ISO14A/7816 protocol
#include "emv/apduinfo.h" // GetAPDUCodeDescription
#include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint
#define TIMEOUT 2000
static int CmdHelp(const char *Cmd);
static int usage_hf_st_info(void) {
PrintAndLogEx(NORMAL, "Usage: hf st info [h]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, "Example:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf st info"));
return PM3_SUCCESS;
}
static int usage_hf_st_sim(void) {
PrintAndLogEx(NORMAL, "\n Emulating ST25TA512B tag with 7 byte UID\n");
PrintAndLogEx(NORMAL, "Usage: hf st sim [h] u <uid> ");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " u : 7 byte UID");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf st sim u 02E2007D0FCA4C"));
return PM3_SUCCESS;
}
static int usage_hf_st_ndef(void) {
PrintAndLogEx(NORMAL, "\n Print NFC Data Exchange Format (NDEF)\n");
PrintAndLogEx(NORMAL, "Usage: hf st ndef [h] p <pwd> ");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " p <pwd> : 16 byte password");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf st ndef p 82E80053D4CA5C0B656D852CC696C8A1"));
return PM3_SUCCESS;
}
// get ST Microelectronics chip model (from UID)
static char *get_st_chip_model(uint8_t pc) {
static char model[40];
char *s = model;
memset(model, 0, sizeof(model));
switch (pc) {
case 0x0:
sprintf(s, "SRIX4K (Special)");
break;
case 0x2:
sprintf(s, "SR176");
break;
case 0x3:
sprintf(s, "SRIX4K");
break;
case 0x4:
sprintf(s, "SRIX512");
break;
case 0x6:
sprintf(s, "SRI512");
break;
case 0x7:
sprintf(s, "SRI4K");
break;
case 0xC:
sprintf(s, "SRT512");
break;
case 0xC4:
sprintf(s, "ST25TA64K");
break;
case 0xE2:
sprintf(s, "ST25??? IKEA Rothult");
break;
case 0xE3:
sprintf(s, "ST25TA02KB");
break;
case 0xE4:
sprintf(s, "ST25TA512B");
break;
case 0xA3:
sprintf(s, "ST25TA02KB-P");
break;
case 0xF3:
sprintf(s, "ST25TA02KB-D");
break;
default :
sprintf(s, "Unknown");
break;
}
return s;
}
/*
// print UID info from SRx chips (ST Microelectronics)
static void print_st_general_info(uint8_t *data, uint8_t len) {
//uid = first 8 bytes in data
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(SwapEndian64(data, 8, 8), len));
PrintAndLogEx(SUCCESS, " MFG: %02X, " _YELLOW_("%s"), data[6], getTagInfo(data[6]));
PrintAndLogEx(SUCCESS, "Chip: %02X, " _YELLOW_("%s"), data[5] >> 2, get_st_chip_model(data[5] >> 2));
}
*/
static void print_st_cc_info(uint8_t *d, uint8_t n) {
if (n < 0x0F) {
PrintAndLogEx(WARNING, "Not enought bytes read from system file");
return;
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "------------ " _CYAN_("Capability Container file") " ------------");
PrintAndLogEx(SUCCESS, " len %u bytes (" _GREEN_("0x%02X") ")", d[1],d[1]);
PrintAndLogEx(SUCCESS, " version %s (" _GREEN_("0x%02X") ")", (d[2] == 0x20) ? "v2.0" : "v1.0", d[2]);
uint16_t maxr = (d[3] << 8 | d[4]);
PrintAndLogEx(SUCCESS, " max bytes read %u bytes ( 0x%04X )", maxr, maxr);
uint16_t maxw = (d[5] << 8 | d[6]);
PrintAndLogEx(SUCCESS, " max bytes write %u bytes ( 0x%04X )", maxw, maxw);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, " NDEF file control TLV {");
PrintAndLogEx(SUCCESS, " (t) type of file ( %02X )", d[7]);
PrintAndLogEx(SUCCESS, " (v) ( %02X )", d[8]);
PrintAndLogEx(SUCCESS, " file id ( %02X%02X )", d[9], d[10]);
uint16_t maxndef = (d[11] << 8 | d[12]);
PrintAndLogEx(SUCCESS, " max NDEF filesize %u bytes ( 0x%04X )", maxndef, maxndef);
PrintAndLogEx(SUCCESS, " ----- " _CYAN_("access rights") " -------");
PrintAndLogEx(SUCCESS, " read ( %02X )", d[13]);
PrintAndLogEx(SUCCESS, " write ( %02X )", d[14]);
PrintAndLogEx(SUCCESS, " }");
PrintAndLogEx(SUCCESS, "----------------- " _CYAN_("raw") " -----------------");
PrintAndLogEx(SUCCESS, "%s", sprint_hex_inrow(d, n));
PrintAndLogEx(NORMAL, "");
}
static void print_st_system_info(uint8_t *d, uint8_t n) {
if (n < 0x12) {
PrintAndLogEx(WARNING, "Not enought bytes read from system file");
return;
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "------------ " _CYAN_("ST System file") " ------------");
uint16_t len = (d[0] << 8 | d[1]);
PrintAndLogEx(SUCCESS, " len %u bytes (" _GREEN_("0x%04X") ")", len, len);
if (d[2] == 0x80) {
PrintAndLogEx(SUCCESS, " ST reserved ( 0x%02X )", d[2]);
} else {
PrintAndLogEx(SUCCESS, " GPO Config ( 0x%02X )", d[2]);
PrintAndLogEx(SUCCESS, " config lock bit ( %s )", ((d[2] & 0x80) == 0x80) ? _RED_("locked") : _GREEN_("unlocked"));
uint8_t conf = (d[2] & 0x70) >> 4;
switch(conf) {
case 0:
PrintAndLogEx(SUCCESS, "");
break;
case 1:
PrintAndLogEx(SUCCESS, "Session opened");
break;
case 2:
PrintAndLogEx(SUCCESS, "WIP");
break;
case 3:
PrintAndLogEx(SUCCESS, "MIP");
break;
case 4:
PrintAndLogEx(SUCCESS, "Interrupt");
break;
case 5:
PrintAndLogEx(SUCCESS, "State Control");
break;
case 6:
PrintAndLogEx(SUCCESS, "RF Busy");
break;
case 7:
PrintAndLogEx(SUCCESS, "Field Detect");
break;
}
}
PrintAndLogEx(SUCCESS, " Event counter config ( 0x%02X )", d[3]);
PrintAndLogEx(SUCCESS, " config lock bit ( %s )", ((d[3] & 0x80) == 0x80) ? _RED_("locked") : _GREEN_("unlocked"));
PrintAndLogEx(SUCCESS, " counter ( %s )", ((d[3] & 0x02) == 0x02) ? _RED_("enabled") : _GREEN_("disable"));
PrintAndLogEx(SUCCESS, " counter increment on ( %s )", ((d[3] & 0x01) == 0x01) ? _YELLOW_("write") : _YELLOW_("read"));
uint32_t counter = (d[4] << 16 | d[5] << 8 | d[6]);
PrintAndLogEx(SUCCESS, " 20bit counter ( 0x%05X )", counter & 0xFFFFF);
PrintAndLogEx(SUCCESS, " Product version ( 0x%02X )", d[7]);
PrintAndLogEx(SUCCESS, " UID " _GREEN_("%s"), sprint_hex_inrow(d + 8, 7));
PrintAndLogEx(SUCCESS, " MFG 0x%02X, " _YELLOW_("%s"), d[8], getTagInfo(d[8]));
PrintAndLogEx(SUCCESS, " Product Code 0x%02X, " _YELLOW_("%s"), d[9], get_st_chip_model(d[9]));
PrintAndLogEx(SUCCESS, " Device# " _YELLOW_("%s"), sprint_hex_inrow(d + 10, 5));
uint16_t mem = (d[0xF] << 8 | d[0x10]);
PrintAndLogEx(SUCCESS, " Memory Size - 1 %u bytes (" _GREEN_("0x%04X") ")", mem, mem);
PrintAndLogEx(SUCCESS, " IC Reference code %u ( 0x%02X )", d[0x12], d[0x12]);
PrintAndLogEx(SUCCESS, "----------------- " _CYAN_("raw") " -----------------");
PrintAndLogEx(SUCCESS, "%s", sprint_hex_inrow(d, n));
PrintAndLogEx(NORMAL, "");
/*
0012
80000000001302E2007D0E8DCC
*/
}
static uint16_t get_sw(uint8_t *d, uint8_t n) {
if (n < 2)
return 0;
n -= 2;
return d[n] * 0x0100 + d[n + 1];
}
// ST rothult
int infoHF_ST(void) {
bool activate_field = true;
bool keep_field_on = true;
uint8_t response[PM3_CMD_DATA_SIZE];
int resplen = 0;
// --------------- Select NDEF Tag application ----------------
uint8_t aSELECT_AID[80];
int aSELECT_AID_n = 0;
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
if (resplen < 2)
return PM3_ESOFT;
uint16_t sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
activate_field = false;
keep_field_on = true;
// --------------- CC file reading ----------------
uint8_t aSELECT_FILE_CC[30];
int aSELECT_FILE_CC_n = 0;
param_gethex_to_eol("00a4000c02e103", 0, aSELECT_FILE_CC, sizeof(aSELECT_FILE_CC), &aSELECT_FILE_CC_n);
res = ExchangeAPDU14a(aSELECT_FILE_CC, aSELECT_FILE_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
uint8_t aREAD_CC[30];
int aREAD_CC_n = 0;
param_gethex_to_eol("00b000000f", 0, aREAD_CC, sizeof(aREAD_CC), &aREAD_CC_n);
res = ExchangeAPDU14a(aREAD_CC, aREAD_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "reading CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
print_st_cc_info(response, resplen - 2);
// --------------- System file reading ----------------
uint8_t aSELECT_FILE_SYS[30];
int aSELECT_FILE_SYS_n = 0;
param_gethex_to_eol("00a4000c02e101", 0, aSELECT_FILE_SYS, sizeof(aSELECT_FILE_SYS), &aSELECT_FILE_SYS_n);
res = ExchangeAPDU14a(aSELECT_FILE_SYS, aSELECT_FILE_SYS_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting system file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
keep_field_on = false;
uint8_t aREAD_SYS[30];
int aREAD_SYS_n = 0;
param_gethex_to_eol("00b0000012", 0, aREAD_SYS, sizeof(aREAD_SYS), &aREAD_SYS_n);
res = ExchangeAPDU14a(aREAD_SYS, aREAD_SYS_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "reading system file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
print_st_system_info(response, resplen - 2);
// PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(response, resplen));
return PM3_SUCCESS;
}
// menu command to get and print all info known about any known 14b tag
static int cmd_hf_st_info(const char *Cmd) {
char c = tolower(param_getchar(Cmd, 0));
if (c == 'h') return usage_hf_st_info();
return infoHF_ST();
}
static int cmd_hf_st_sim(const char *Cmd) {
char c = tolower(param_getchar(Cmd, 0));
if (c == 'h' || c == 0x00) return usage_hf_st_sim();
int uidlen = 0;
uint8_t cmdp = 0;
uint8_t uid[7] = {0};
if (c == 'u') {
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
uidlen >>= 1;
if (uidlen != 7) {
return usage_hf_st_sim();
}
}
char param[40];
snprintf(param, sizeof(param), "t 10 u %s", sprint_hex_inrow(uid, uidlen));
return CmdHF14ASim(param);
}
static int cmd_hf_st_ndef(const char *Cmd) {
char c = tolower(param_getchar(Cmd, 0));
if (c == 'h' || c == 0x00) return usage_hf_st_ndef();
int pwdlen = 0;
uint8_t cmdp = 0;
uint8_t pwd[16] = {0};
if (c == 'p') {
param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen);
pwdlen >>= 1;
if (pwdlen != 16) {
return usage_hf_st_ndef();
}
}
bool activate_field = true;
bool keep_field_on = true;
uint8_t response[PM3_CMD_DATA_SIZE];
int resplen = 0;
// --------------- Select NDEF Tag application ----------------
uint8_t aSELECT_AID[80];
int aSELECT_AID_n = 0;
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
if (resplen < 2)
return PM3_ESOFT;
uint16_t sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
activate_field = false;
keep_field_on = true;
// --------------- NDEF file reading ----------------
uint8_t aSELECT_FILE_NDEF[30];
int aSELECT_FILE_NDEF_n = 0;
param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
// --------------- VERIFY ----------------
uint8_t aVERIFY[30];
int aVERIFY_n = 0;
param_gethex_to_eol("0020000100", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw == 0x6300) {
// need to provide 16byte password
param_gethex_to_eol("0020000110", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen);
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
}
keep_field_on = false;
uint8_t aREAD_NDEF[30];
int aREAD_NDEF_n = 0;
param_gethex_to_eol("00b000001d", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
res = ExchangeAPDU14a(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "reading NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
NDEFRecordsDecodeAndPrint(response + 2, resplen - 4);
return PM3_SUCCESS;
}
static int cmd_hf_st_list(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("7816");
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"info", cmd_hf_st_info, IfPm3Iso14443a, "Tag information"},
{"list", cmd_hf_st_list, AlwaysAvailable, "List ISO 14443A/7816 history"},
{"ndef", cmd_hf_st_ndef, AlwaysAvailable, "read NDEF file on tag"},
{"sim", cmd_hf_st_sim, IfPm3Iso14443a, "Fake ISO 14443A/ST tag"},
{NULL, NULL, NULL, NULL}
};
static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdsHelp(CommandTable);
return PM3_SUCCESS;
}
int CmdHF_ST(const char *Cmd) {
clearCommandBuffer();
return CmdsParse(CommandTable, Cmd);
}

19
client/src/cmdhfst.h Normal file
View file

@ -0,0 +1,19 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2020 iceman1001
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// High frequency ISO14443A / ST commands
//-----------------------------------------------------------------------------
#ifndef CMDHFST_H__
#define CMDHFST_H__
#include "common.h"
int CmdHF_ST(const char *Cmd);
int infoHF_ST(void);
#endif

1065
client/src/cmdhfwaveshare.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
//-----------------------------------------------------------------------------
// Waveshare commands
//-----------------------------------------------------------------------------
#ifndef CMDHFWAVESHARE_H__
#define CMDHFWAVESHARE_H__
int CmdHFWaveshare(const char *Cmd);
#endif

View file

@ -61,31 +61,43 @@ static bool g_lf_threshold_set = false;
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static int usage_lf_cmdread(void) { static int usage_lf_cmdread(void) {
PrintAndLogEx(NORMAL, "Usage: lf cmdread d <delay period> z <zero period> o <one period> c <cmdbytes>"); PrintAndLogEx(NORMAL, "Usage: lf cmdread d <delay period> z <zero period> o <one period> c <cmdbytes> [q] [s #samples] [@]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " d <delay> delay OFF period, (0 for bitbang mode) (decimal)"); PrintAndLogEx(NORMAL, " d <delay> delay OFF period, (0 for bitbang mode) (decimal)");
PrintAndLogEx(NORMAL, " z <zero> ZERO time period (decimal)"); PrintAndLogEx(NORMAL, " z <zero> ZERO time period (decimal)");
PrintAndLogEx(NORMAL, " o <one> ONE time period (decimal)"); PrintAndLogEx(NORMAL, " o <one> ONE time period (decimal)");
PrintAndLogEx(NORMAL, " c <cmd> Command bytes (in ones and zeros)"); PrintAndLogEx(NORMAL, " c <cmd> Command bytes (in ones and zeros)");
PrintAndLogEx(NORMAL, " q silent (optional)");
PrintAndLogEx(NORMAL, " s #samples number of samples to collect (optional)");
PrintAndLogEx(NORMAL, " @ run continuously until a key is pressed (optional)");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, " ************* " _YELLOW_("All periods in microseconds (us)")); PrintAndLogEx(NORMAL, " ************* " _YELLOW_("All periods in microseconds (us)"));
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf cmdread d 80 z 100 o 200 c 11000"); PrintAndLogEx(NORMAL, "- probing for HT2:");
PrintAndLogEx(NORMAL, " lf cmdread d 50 z 116 o 166 c 011000");
PrintAndLogEx(NORMAL, "- probing for HT2, oscilloscope style:");
PrintAndLogEx(NORMAL, " data plot");
PrintAndLogEx(NORMAL, " lf cmdread d 50 z 116 o 166 c 011000 q s 2000 @");
PrintAndLogEx(NORMAL, "Extras:"); PrintAndLogEx(NORMAL, "Extras:");
PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters."); PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters.");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_lf_read(void) { static int usage_lf_read(void) {
PrintAndLogEx(NORMAL, "Usage: lf read [h] [s] [d numofsamples]"); PrintAndLogEx(NORMAL, "Usage: lf read [h] [q] [s #samples] [@]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " d #samples # samples to collect (optional)"); PrintAndLogEx(NORMAL, " q silent (optional)");
PrintAndLogEx(NORMAL, " s silent"); PrintAndLogEx(NORMAL, " s #samples number of samples to collect (optional)");
PrintAndLogEx(NORMAL, " @ run continuously until a key is pressed (optional)");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf read s d 12000 - collects 12000 samples silent"); PrintAndLogEx(NORMAL, " lf read");
PrintAndLogEx(NORMAL, " lf read"); PrintAndLogEx(NORMAL, "- collecting quietly 12000 samples:");
PrintAndLogEx(NORMAL, " lf read q s 12000 - ");
PrintAndLogEx(NORMAL, "- oscilloscope style:");
PrintAndLogEx(NORMAL, " data plot");
PrintAndLogEx(NORMAL, " lf read q s 3000 @");
PrintAndLogEx(NORMAL, "Extras:"); PrintAndLogEx(NORMAL, "Extras:");
PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters."); PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters.");
return PM3_SUCCESS; return PM3_SUCCESS;
@ -307,14 +319,22 @@ int CmdLFCommandRead(const char *Cmd) {
if (!session.pm3_present) return PM3_ENOTTY; if (!session.pm3_present) return PM3_ENOTTY;
bool errors = false; bool errors = false;
bool verbose = true;
bool continuous = false;
uint32_t samples = 0;
uint16_t datalen = 0; uint16_t datalen = 0;
uint8_t payload_header_size = 12;
struct p { struct p {
uint32_t delay; uint32_t delay;
uint16_t ones; uint16_t ones;
uint16_t zeros; uint16_t zeros;
uint8_t data[PM3_CMD_DATA_SIZE - 8]; uint32_t samples : 31;
bool verbose : 1;
uint8_t data[PM3_CMD_DATA_SIZE - payload_header_size];
} PACKED payload; } PACKED payload;
payload.samples = samples;
payload.verbose = verbose;
uint8_t cmdp = 0; uint8_t cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
@ -337,6 +357,20 @@ int CmdLFCommandRead(const char *Cmd) {
payload.ones = param_get32ex(Cmd, cmdp + 1, 0, 10) & 0xFFFF; payload.ones = param_get32ex(Cmd, cmdp + 1, 0, 10) & 0xFFFF;
cmdp += 2; cmdp += 2;
break; break;
case 's':
samples = param_get32ex(Cmd, cmdp + 1, 0, 10);
payload.samples = samples;
cmdp += 2;
break;
case 'q':
verbose = false;
payload.verbose = verbose;
cmdp++;
break;
case '@':
continuous = true;
cmdp++;
break;
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
@ -354,33 +388,51 @@ int CmdLFCommandRead(const char *Cmd) {
//Validations //Validations
if (errors || cmdp == 0) return usage_lf_cmdread(); if (errors || cmdp == 0) return usage_lf_cmdread();
if (continuous) {
PrintAndLogEx(SUCCESS, "sending"); PrintAndLogEx(INFO, "Press " _GREEN_("Enter") " to exit");
clearCommandBuffer(); }
SendCommandNG(CMD_LF_MOD_THEN_ACQ_RAW_ADC, (uint8_t *)&payload, 8 + datalen); if (verbose) {
PrintAndLogEx(SUCCESS, "Sending command...");
PacketResponseNG resp;
uint8_t i = 10;
// 20sec wait loop
while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) {
PrintAndLogEx(NORMAL, "." NOLF);
i--;
} }
PrintAndLogEx(NORMAL, "");
if (resp.status == PM3_SUCCESS) { int ret = PM3_SUCCESS;
if (i) { do {
PrintAndLogEx(SUCCESS, "downloading response signal data"); clearCommandBuffer();
getSamples(0, false); SendCommandNG(CMD_LF_MOD_THEN_ACQ_RAW_ADC, (uint8_t *)&payload, payload_header_size + datalen);
return PM3_SUCCESS;
} else { PacketResponseNG resp;
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT; uint8_t i = 10;
// 20sec wait loop
while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) {
if (verbose) {
PrintAndLogEx(NORMAL, "." NOLF);
}
i--;
} }
} if (verbose) {
PrintAndLogEx(WARNING, "command failed."); PrintAndLogEx(NORMAL, "");
return PM3_ESOFT; }
if (resp.status == PM3_SUCCESS) {
if (i) {
if (verbose) {
PrintAndLogEx(SUCCESS, "downloading response signal data");
}
getSamples(samples, false);
ret = PM3_SUCCESS;
} else {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
} else {
PrintAndLogEx(WARNING, "command failed.");
return PM3_ESOFT;
}
if (kbd_enter_pressed()) {
break;
}
} while (continuous);
return ret;
} }
int CmdFlexdemod(const char *Cmd) { int CmdFlexdemod(const char *Cmd) {
@ -595,8 +647,8 @@ int lf_read(bool verbose, uint32_t samples) {
if (!session.pm3_present) return PM3_ENOTTY; if (!session.pm3_present) return PM3_ENOTTY;
struct p { struct p {
bool verbose; uint32_t samples : 31;
uint32_t samples; bool verbose : 1;
} PACKED; } PACKED;
struct p payload; struct p payload;
@ -627,20 +679,25 @@ int CmdLFRead(const char *Cmd) {
bool errors = false; bool errors = false;
bool verbose = true; bool verbose = true;
bool continuous = false;
uint32_t samples = 0; uint32_t samples = 0;
uint8_t cmdp = 0; uint8_t cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': case 'h':
return usage_lf_read(); return usage_lf_read();
case 'd': case 's':
samples = param_get32ex(Cmd, cmdp + 1, 0, 10); samples = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2; cmdp += 2;
break; break;
case 's': case 'q':
verbose = false; verbose = false;
cmdp++; cmdp++;
break; break;
case '@':
continuous = true;
cmdp++;
break;
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
@ -650,8 +707,17 @@ int CmdLFRead(const char *Cmd) {
//Validations //Validations
if (errors) return usage_lf_read(); if (errors) return usage_lf_read();
if (continuous) {
return lf_read(verbose, samples); PrintAndLogEx(INFO, "Press " _GREEN_("Enter") " to exit");
}
int ret = PM3_SUCCESS;
do {
ret = lf_read(verbose, samples);
if (kbd_enter_pressed()) {
break;
}
} while (continuous);
return ret;
} }
int CmdLFSniff(const char *Cmd) { int CmdLFSniff(const char *Cmd) {
@ -1200,6 +1266,7 @@ static bool CheckChipType(bool getDeviceData) {
PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("T55xx")); PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("T55xx"));
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf t55xx`") " commands"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf t55xx`") " commands");
retval = true; retval = true;
goto out;
} }
// check for em4x50 chips // check for em4x50 chips

View file

@ -50,19 +50,18 @@ static int CmdHelp(const char *Cmd);
static int usage_lf_fdx_clone(void) { static int usage_lf_fdx_clone(void) {
PrintAndLogEx(NORMAL, "Clone a FDX-B animal tag to a T55x7 or Q5/T5555 tag."); PrintAndLogEx(NORMAL, "Clone a FDX-B animal tag to a T55x7 or Q5/T5555 tag.");
PrintAndLogEx(NORMAL, "Usage: lf fdx clone [h] <country id> <animal id> <extended> <Q5>"); PrintAndLogEx(NORMAL, "Usage: lf fdx clone [h] [c <country code>] [a <national code>] [e <extended>] <s> <Q5>");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <country id> : Country id"); PrintAndLogEx(NORMAL, " c <country> : (dec) Country code");
PrintAndLogEx(NORMAL, " <animal id> : Animal id"); PrintAndLogEx(NORMAL, " n <national> : (dec) National code");
PrintAndLogEx(NORMAL, " <extended> : Extended data"); PrintAndLogEx(NORMAL, " e <extended> : (hex) Extended data");
//reserved/rfu PrintAndLogEx(NORMAL, " s : Set animal bit");
//is animal tag PrintAndLogEx(NORMAL, " <Q5> : Specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, " <Q5> : Specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone 999 112233")); PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone c 999 n 112233 s"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone 999 112233 16a")); PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone c 999 n 112233 e 16a"));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -70,33 +69,37 @@ static int usage_lf_fdx_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of FDX-B animal tag"); PrintAndLogEx(NORMAL, "Enables simulation of FDX-B animal tag");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued."); PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf fdx sim [h] <country id> <animal id> <extended>"); PrintAndLogEx(NORMAL, "Usage: lf fdx sim [h] [c <country code>] [n <national code>] [e <extended>] <s> <Q5>");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <country id> : Country ID"); PrintAndLogEx(NORMAL, " c <country> : (dec) Country code");
PrintAndLogEx(NORMAL, " <animal id> : Animal ID"); PrintAndLogEx(NORMAL, " n <national> : (dec) National code");
PrintAndLogEx(NORMAL, " <extended> : Extended data"); PrintAndLogEx(NORMAL, " e <extended> : (hex) Extended data");
PrintAndLogEx(NORMAL, " s : Set animal bit");
PrintAndLogEx(NORMAL, " <Q5> : Specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx sim 999 112233")); PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx sim c 999 n 112233 s"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx sim 999 112233 16a")); PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx sim c 999 n 112233 e 16a"));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
// clearing the topbit needed for the preambl detection. // clearing the topbit needed for the preambl detection.
static void verify_values(uint64_t *animalid, uint32_t *countryid, uint32_t *extended) { static void verify_values(uint64_t *animalid, uint32_t *countryid, uint32_t *extended, uint8_t *is_animal) {
if ((*animalid & 0x3FFFFFFFFF) != *animalid) { if ((*animalid & 0x3FFFFFFFFF) != *animalid) {
*animalid &= 0x3FFFFFFFFF; *animalid &= 0x3FFFFFFFFF;
PrintAndLogEx(INFO, "Animal ID truncated to 38bits: " _YELLOW_("%"PRIx64), *animalid); PrintAndLogEx(INFO, "Animal ID truncated to 38bits: " _YELLOW_("%"PRIx64), *animalid);
} }
if ((*countryid & 0x3ff) != *countryid) { if ((*countryid & 0x3FF) != *countryid) {
*countryid &= 0x3ff; *countryid &= 0x3FF;
PrintAndLogEx(INFO, "Country ID truncated to 10bits:" _YELLOW_("%03d"), *countryid); PrintAndLogEx(INFO, "Country ID truncated to 10bits:" _YELLOW_("%03d"), *countryid);
} }
if ((*extended & 0xfff) != *extended) { if ((*extended & 0xFFF) != *extended) {
*extended &= 0xfff; *extended &= 0xFFF;
PrintAndLogEx(INFO, "Extended truncated to 24bits: " _YELLOW_("0x%03X"), *extended); PrintAndLogEx(INFO, "Extended truncated to 24bits: " _YELLOW_("0x%03X"), *extended);
} }
*is_animal &= 0x01;
} }
static inline uint32_t bitcount(uint32_t a) { static inline uint32_t bitcount(uint32_t a) {
@ -228,6 +231,8 @@ int demodFDX(void) {
// set and leave DemodBuffer intact // set and leave DemodBuffer intact
setDemodBuff(DemodBuffer, 128, preambleIndex); setDemodBuff(DemodBuffer, 128, preambleIndex);
setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex * g_DemodClock)); setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex * g_DemodClock));
// remove marker bits (1's every 9th digit after preamble) (pType = 2) // remove marker bits (1's every 9th digit after preamble) (pType = 2)
size = removeParity(DemodBuffer, 11, 9, 2, 117); size = removeParity(DemodBuffer, 11, 9, 2, 117);
if (size != 104) { if (size != 104) {
@ -236,29 +241,43 @@ int demodFDX(void) {
} }
//got a good demod //got a good demod
uint8_t offset;
uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(DemodBuffer + 32, 6)) << 32) | bytebits_to_byteLSBF(DemodBuffer, 32); uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(DemodBuffer + 32, 6)) << 32) | bytebits_to_byteLSBF(DemodBuffer, 32);
uint16_t countryCode = bytebits_to_byteLSBF(DemodBuffer + 38, 10);
uint8_t dataBlockBit = DemodBuffer[48]; offset = 38;
uint32_t reservedCode = bytebits_to_byteLSBF(DemodBuffer + 49, 14); uint16_t countryCode = bytebits_to_byteLSBF(DemodBuffer + offset, 10);
uint8_t animalBit = DemodBuffer[63];
uint16_t crc = bytebits_to_byteLSBF(DemodBuffer + 64, 16); offset += 10;
uint32_t extended = bytebits_to_byteLSBF(DemodBuffer + 80, 24); uint8_t dataBlockBit = DemodBuffer[offset];
offset++;
uint32_t reservedCode = bytebits_to_byteLSBF(DemodBuffer + offset, 14);
offset += 14;
uint8_t animalBit = DemodBuffer[offset];
offset++;
uint16_t crc = bytebits_to_byteLSBF(DemodBuffer + offset, 16);
offset += 16;
uint32_t extended = bytebits_to_byteLSBF(DemodBuffer + offset, 24);
uint64_t rawid = (uint64_t)(bytebits_to_byte(DemodBuffer, 32)) << 32 | bytebits_to_byte(DemodBuffer + 32, 32); uint64_t rawid = (uint64_t)(bytebits_to_byte(DemodBuffer, 32)) << 32 | bytebits_to_byte(DemodBuffer + 32, 32);
uint8_t raw[8]; uint8_t raw[8];
num_to_bytes(rawid, 8, raw); num_to_bytes(rawid, 8, raw);
PrintAndLogEx(SUCCESS, "FDX-B / ISO 11784/5 Animal"); PrintAndLogEx(SUCCESS, "FDX-B / ISO 11784/5 Animal");
PrintAndLogEx(SUCCESS, "Animal ID " _GREEN_("%04u-%012"PRIu64), countryCode, NationalCode); PrintAndLogEx(SUCCESS, "Animal ID " _GREEN_("%04u-%012"PRIu64), countryCode, NationalCode);
PrintAndLogEx(SUCCESS, "National Code " _GREEN_("%012" PRIu64) " (0x%" PRIx64 ")", NationalCode, NationalCode); PrintAndLogEx(SUCCESS, "National Code " _GREEN_("%012" PRIu64) " (0x%" PRIX64 ")", NationalCode, NationalCode);
PrintAndLogEx(SUCCESS, "Country Code %04u", countryCode); PrintAndLogEx(SUCCESS, "Country Code " _GREEN_("%04u"), countryCode);
PrintAndLogEx(SUCCESS, "Reserved/RFU %u (0x04%X)", reservedCode, reservedCode); PrintAndLogEx(SUCCESS, "Reserved/RFU %u (0x%04X)", reservedCode, reservedCode);
PrintAndLogEx(SUCCESS, "Animal Tag %s", animalBit ? _YELLOW_("True") : "False"); PrintAndLogEx(SUCCESS, " Animal bit set? %s", animalBit ? _YELLOW_("True") : "False");
PrintAndLogEx(SUCCESS, "Has extended data %s [0x%X]", dataBlockBit ? _YELLOW_("True") : "False", extended); PrintAndLogEx(SUCCESS, " Data block? %s [value 0x%X]", dataBlockBit ? _YELLOW_("True") : "False", extended);
uint8_t c[] = {0, 0}; uint8_t c[] = {0, 0};
compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]); compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]);
PrintAndLogEx(SUCCESS, "CRC-16 0x%04X (%s) ", crc, (crc == (c[1] << 8 | c[0])) ? _GREEN_("ok") : _RED_("fail")); PrintAndLogEx(SUCCESS, "CRC-16 0x%04X (%s)", crc, (crc == (c[1] << 8 | c[0])) ? _GREEN_("ok") : _RED_("fail"));
// iceman: crc doesn't protect the extended data?
PrintAndLogEx(SUCCESS, "Raw " _GREEN_("%s"), sprint_hex(raw, 8)); PrintAndLogEx(SUCCESS, "Raw " _GREEN_("%s"), sprint_hex(raw, 8));
if (g_debugMode) { if (g_debugMode) {
@ -327,21 +346,61 @@ static int CmdFdxRead(const char *Cmd) {
static int CmdFdxClone(const char *Cmd) { static int CmdFdxClone(const char *Cmd) {
uint32_t countryid = 0, extended = 0; uint32_t country_code = 0, extended = 0;
uint64_t animalid = 0; uint64_t national_code = 0;
uint8_t is_animal = 0, cmdp = 0;
bool errors = false, has_extended = false, q5 = false;
char cmdp = tolower(param_getchar(Cmd, 0)); while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_fdx_clone(); switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_fdx_clone();
case 'c': {
country_code = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
}
case 'n': {
national_code = param_get64ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
}
case 'e': {
extended = param_get32ex(Cmd, cmdp + 1, 0, 16);
has_extended = true;
cmdp += 2;
break;
}
case 's': {
is_animal = 1;
cmdp++;
break;
}
case 'q': {
q5 = true;
cmdp++;
break;
}
default: {
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
}
if (errors || strlen(Cmd) == 0) return usage_lf_fdx_clone();
countryid = param_get32ex(Cmd, 0, 0, 10); verify_values(&national_code, &country_code, &extended, &is_animal);
animalid = param_get64ex(Cmd, 1, 0, 10);
extended = param_get32ex(Cmd, 2, 0, 16);
verify_values(&animalid, &countryid, &extended); PrintAndLogEx(INFO, " Country code %"PRIu32, country_code);
PrintAndLogEx(INFO, " National code %"PRIu64, national_code);
PrintAndLogEx(INFO, " Set animal bit %c", (is_animal) ? 'Y' : 'N');
PrintAndLogEx(INFO, "Set data block bit %c", (has_extended) ? 'Y' : 'N');
PrintAndLogEx(INFO, " Extended data 0x%"PRIX32, extended);
PrintAndLogEx(INFO, " RFU 0");
uint8_t *bits = calloc(128, sizeof(uint8_t)); uint8_t *bits = calloc(128, sizeof(uint8_t));
if (getFDXBits(national_code, country_code, is_animal, has_extended, extended, bits) != PM3_SUCCESS) {
if (getFDXBits(animalid, countryid, 1, (extended > 0), extended, bits) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation."); PrintAndLogEx(ERR, "Error with tag bitstream generation.");
free(bits); free(bits);
return PM3_ESOFT; return PM3_ESOFT;
@ -350,7 +409,6 @@ static int CmdFdxClone(const char *Cmd) {
uint32_t blocks[5] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0, 0}; uint32_t blocks[5] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0, 0};
//Q5 //Q5
bool q5 = tolower(param_getchar(Cmd, 2)) == 'q';
if (q5) if (q5)
blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT; blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT;
@ -362,7 +420,7 @@ static int CmdFdxClone(const char *Cmd) {
free(bits); free(bits);
PrintAndLogEx(INFO, "Preparing to clone FDX-B to " _YELLOW_("%s") " with animal ID: " _GREEN_("%04u-%"PRIu64)" (extended 0x%X)", (q5) ? "Q5/T5555" : "T55x7", countryid, animalid, extended); PrintAndLogEx(INFO, "Preparing to clone FDX-B to " _YELLOW_("%s") " with animal ID: " _GREEN_("%04u-%"PRIu64), (q5) ? "Q5/T5555" : "T55x7", country_code, national_code);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -372,24 +430,59 @@ static int CmdFdxClone(const char *Cmd) {
} }
static int CmdFdxSim(const char *Cmd) { static int CmdFdxSim(const char *Cmd) {
uint32_t countryid = 0, extended = 0;
uint64_t animalid = 0;
char cmdp = tolower(param_getchar(Cmd, 0)); uint32_t country_code = 0, extended = 0;
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_fdx_sim(); uint64_t national_code = 0;
uint8_t is_animal = 0, cmdp = 0;
bool errors = false, has_extended = false;
countryid = param_get32ex(Cmd, 0, 0, 10); while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
animalid = param_get64ex(Cmd, 1, 0, 10); switch (tolower(param_getchar(Cmd, cmdp))) {
extended = param_get32ex(Cmd, 2, 0, 16); case 'h':
return usage_lf_fdx_sim();
case 'c': {
country_code = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
}
case 'n': {
national_code = param_get64ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
}
case 'e': {
extended = param_get32ex(Cmd, cmdp + 1, 0, 10);
has_extended = true;
cmdp += 2;
break;
}
case 's': {
is_animal = 1;
cmdp++;
break;
}
default: {
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
}
if (errors) return usage_lf_fdx_sim();
verify_values(&animalid, &countryid, &extended); verify_values(&national_code, &country_code, &extended, &is_animal);
PrintAndLogEx(SUCCESS, "Simulating FDX-B animal ID: " _GREEN_("%04u-%"PRIu64)" (extended 0x%X)", countryid, animalid, extended); PrintAndLogEx(INFO, " Country code %"PRIu32, country_code);
PrintAndLogEx(INFO, " National code %"PRIu64, national_code);
PrintAndLogEx(INFO, " Set animal bit %c", (is_animal) ? 'Y' : 'N');
PrintAndLogEx(INFO, "Set data block bit %c", (has_extended) ? 'Y' : 'N');
PrintAndLogEx(INFO, " Extended data 0x%"PRIX32, extended);
PrintAndLogEx(INFO, " RFU 0");
PrintAndLogEx(SUCCESS, "Simulating FDX-B animal ID: " _GREEN_("%04u-%"PRIu64), country_code, national_code);
//getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits)
uint8_t *bits = calloc(128, sizeof(uint8_t)); uint8_t *bits = calloc(128, sizeof(uint8_t));
if (getFDXBits(national_code, country_code, is_animal, (extended > 0), extended, bits) != PM3_SUCCESS) {
if (getFDXBits(animalid, countryid, 1, (extended > 0), extended, bits) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation."); PrintAndLogEx(ERR, "Error with tag bitstream generation.");
free(bits); free(bits);
return PM3_ESOFT; return PM3_ESOFT;
@ -453,7 +546,7 @@ int detectFDXB(uint8_t *dest, size_t *size) {
return (int)startIdx; return (int)startIdx;
} }
int getFDXBits(uint64_t national_id, uint16_t country, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits) { int getFDXBits(uint64_t national_code, uint16_t country_code, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits) {
// add preamble ten 0x00 and one 0x01 // add preamble ten 0x00 and one 0x01
memset(bits, 0x00, 10); memset(bits, 0x00, 10);
@ -471,21 +564,21 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t is_animal, uint8_
num_to_bytebitsLSBF(0x00 >> 7, 7, bits + 74); num_to_bytebitsLSBF(0x00 >> 7, 7, bits + 74);
// add animal flag - OK // add animal flag - OK
bits[65] = is_animal; bits[81] = is_animal;
// add extended flag - OK // add extended flag - OK
bits[81] = is_extended; bits[65] = is_extended;
// add national code 40bits - OK // add national code 40bits - OK
num_to_bytebitsLSBF(national_id >> 0, 8, bits + 11); num_to_bytebitsLSBF(national_code >> 0, 8, bits + 11);
num_to_bytebitsLSBF(national_id >> 8, 8, bits + 20); num_to_bytebitsLSBF(national_code >> 8, 8, bits + 20);
num_to_bytebitsLSBF(national_id >> 16, 8, bits + 29); num_to_bytebitsLSBF(national_code >> 16, 8, bits + 29);
num_to_bytebitsLSBF(national_id >> 24, 8, bits + 38); num_to_bytebitsLSBF(national_code >> 24, 8, bits + 38);
num_to_bytebitsLSBF(national_id >> 32, 6, bits + 47); num_to_bytebitsLSBF(national_code >> 32, 6, bits + 47);
// add country code - OK // add country code - OK
num_to_bytebitsLSBF(country >> 0, 2, bits + 53); num_to_bytebitsLSBF(country_code >> 0, 2, bits + 53);
num_to_bytebitsLSBF(country >> 2, 8, bits + 56); num_to_bytebitsLSBF(country_code >> 2, 8, bits + 56);
// add crc-16 - OK // add crc-16 - OK
uint8_t raw[8]; uint8_t raw[8];
@ -501,6 +594,10 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t is_animal, uint8_
num_to_bytebitsLSBF(extended >> 0, 8, bits + 101); num_to_bytebitsLSBF(extended >> 0, 8, bits + 101);
num_to_bytebitsLSBF(extended >> 8, 8, bits + 110); num_to_bytebitsLSBF(extended >> 8, 8, bits + 110);
num_to_bytebitsLSBF(extended >> 16, 8, bits + 119); num_to_bytebitsLSBF(extended >> 16, 8, bits + 119);
// 8 16 24 32 40 48 49
// A8 28 0C 92 EA 6F 00 01
// A8 28 0C 92 EA 6F 80 00
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -14,7 +14,7 @@
int CmdLFFdx(const char *Cmd); int CmdLFFdx(const char *Cmd);
int detectFDXB(uint8_t *dest, size_t *size); int detectFDXB(uint8_t *dest, size_t *size);
int demodFDX(void); int demodFDX(void);
int getFDXBits(uint64_t national_id, uint16_t country, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits); int getFDXBits(uint64_t national_code, uint16_t country_code, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits);
#endif #endif

View file

@ -93,32 +93,35 @@ static int CmdGuardDemod(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
//got a good demod of 96 bits // got a good demod of 96 bits
uint8_t ByteStream[8] = {0x00};
uint8_t plain[8] = {0x00};
uint8_t xorKey = 0; uint8_t xorKey = 0;
size_t startIdx = preambleIndex + 6; //start after 6 bit preamble size_t startIdx = preambleIndex + 6; //start after 6 bit preamble
uint8_t bits_no_spacer[90]; uint8_t bits_no_spacer[90];
//so as to not mess with raw DemodBuffer copy to a new sample array
// not mess with raw DemodBuffer copy to a new sample array
memcpy(bits_no_spacer, DemodBuffer + startIdx, 90); memcpy(bits_no_spacer, DemodBuffer + startIdx, 90);
// remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72)) // remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72))
size_t len = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run size_t len = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run
if (len != 72) { if (len != 72) {
PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII spacer removal did not produce 72 bits: %zu, start: %zu", len, startIdx); PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII spacer removal did not produce 72 bits: %zu, start: %zu", len, startIdx);
return PM3_ESOFT; return PM3_ESOFT;
} }
// get key and then get all 8 bytes of payload decoded // get key and then get all 8 bytes of payload decoded
xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8); xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8);
for (size_t idx = 0; idx < 8; idx++) { for (size_t idx = 0; idx < 8; idx++) {
ByteStream[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer + 8 + (idx * 8), 8)) ^ xorKey; plain[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer + 8 + (idx * 8), 8)) ^ xorKey;
PrintAndLogEx(DEBUG, "DEBUG: gProxII byte %zu after xor: %02x", idx, ByteStream[idx]); PrintAndLogEx(DEBUG, "DEBUG: gProxII byte %zu after xor: %02x", idx, plain[idx]);
} }
setDemodBuff(DemodBuffer, 96, preambleIndex); setDemodBuff(DemodBuffer, 96, preambleIndex);
setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex * g_DemodClock)); setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex * g_DemodClock));
//ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data //plain contains 8 Bytes (64 bits) of decrypted raw tag data
uint8_t fmtLen = ByteStream[0] >> 2; uint8_t fmtLen = plain[0] >> 2;
uint32_t FC = 0; uint32_t FC = 0;
uint32_t Card = 0; uint32_t Card = 0;
//get raw 96 bits to print //get raw 96 bits to print
@ -128,12 +131,12 @@ static int CmdGuardDemod(const char *Cmd) {
bool unknown = false; bool unknown = false;
switch (fmtLen) { switch (fmtLen) {
case 36: case 36:
FC = ((ByteStream[3] & 0x7F) << 7) | (ByteStream[4] >> 1); FC = ((plain[3] & 0x7F) << 7) | (plain[4] >> 1);
Card = ((ByteStream[4] & 1) << 19) | (ByteStream[5] << 11) | (ByteStream[6] << 3) | (ByteStream[7] >> 5); Card = ((plain[4] & 1) << 19) | (plain[5] << 11) | (plain[6] << 3) | ((plain[7] & 0xE0) >> 5);
break; break;
case 26: case 26:
FC = ((ByteStream[3] & 0x7F) << 1) | (ByteStream[4] >> 7); FC = ((plain[3] & 0x7F) << 1) | (plain[4] >> 7);
Card = ((ByteStream[4] & 0x7F) << 9) | (ByteStream[5] << 1) | (ByteStream[6] >> 7); Card = ((plain[4] & 0x7F) << 9) | (plain[5] << 1) | (plain[6] >> 7);
break; break;
default : default :
unknown = true; unknown = true;
@ -309,14 +312,12 @@ int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
break; break;
} }
case 36: { case 36: {
// FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1);
// Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5);
rawbytes[1] = (36 << 2); rawbytes[1] = (36 << 2);
// Get 26 wiegand from FacilityCode, CardNumber // Get wiegand from FacilityCode 14bits, CardNumber 20bits
uint8_t wiegand[34]; uint8_t wiegand[36];
memset(wiegand, 0x00, sizeof(wiegand)); memset(wiegand, 0x00, sizeof(wiegand));
num_to_bytebits(fc, 8, wiegand); num_to_bytebits(fc, 14, wiegand);
num_to_bytebits(cn, 26, wiegand + 8); num_to_bytebits(cn, 20, wiegand + 14);
// add wiegand parity bits (dest, source, len) // add wiegand parity bits (dest, source, len)
wiegand_add_parity(pre, wiegand, 34); wiegand_add_parity(pre, wiegand, 34);
@ -351,28 +352,27 @@ int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
rawbytes[3] = 0; rawbytes[3] = 0;
// add wiegand to rawbytes // add wiegand to rawbytes
for (i = 0; i < 4; ++i) for (i = 0; i < 5; ++i)
rawbytes[i + 4] = bytebits_to_byte(pre + (i * 8), 8); rawbytes[i + 4] = bytebits_to_byte(pre + (i * 8), 8);
PrintAndLogEx(DEBUG, " WIE | %s\n", sprint_hex(rawbytes, sizeof(rawbytes))); PrintAndLogEx(DEBUG, " WIE | %s", sprint_hex(rawbytes, sizeof(rawbytes)));
// XOR (only works on wiegand stuff) // XOR (only works on wiegand stuff)
for (i = 1; i < 12; ++i) for (i = 1; i < sizeof(rawbytes); ++i)
rawbytes[i] ^= xorKey ; rawbytes[i] ^= xorKey ;
PrintAndLogEx(DEBUG, " XOR | %s \n", sprint_hex(rawbytes, sizeof(rawbytes))); PrintAndLogEx(DEBUG, " XOR | %s", sprint_hex(rawbytes, sizeof(rawbytes)));
// convert rawbytes to bits in pre // convert rawbytes to bits in pre
for (i = 0; i < 12; ++i) for (i = 0; i < sizeof(rawbytes); ++i)
num_to_bytebitsLSBF(rawbytes[i], 8, pre + (i * 8)); num_to_bytebitsLSBF(rawbytes[i], 8, pre + (i * 8));
PrintAndLogEx(DEBUG, "\n Raw | %s \n", sprint_hex(rawbytes, sizeof(rawbytes))); PrintAndLogEx(DEBUG, " Raw | %s", sprint_hex(rawbytes, sizeof(rawbytes)));
PrintAndLogEx(DEBUG, " Raw | %s\n", sprint_bin(pre, 64)); PrintAndLogEx(DEBUG, " Raw | %s", sprint_bin(pre, 96));
// add spacer bit 0 every 4 bits, starting with index 0, // add spacer bit 0 every 4 bits, starting with index 0,
// 12 bytes, 24 nibbles. 24+1 extra bites. 3bytes. ie 9bytes | 1byte xorkey, 8bytes rawdata (64bits, should be enough for a 40bit wiegand) // 12 bytes, 24 nibbles. 24+1 extra bites. 3bytes. ie 9bytes | 1byte xorkey, 8bytes rawdata (72bits, should be enough for a 40bit wiegand)
addParity(pre, guardBits + 6, 64, 5, 3); addParity(pre, guardBits + 6, 72, 5, 3);
// preamble // preamble
guardBits[0] = 1; guardBits[0] = 1;

View file

@ -829,7 +829,7 @@ static int CmdT55xxSetConfig(const char *Cmd) {
return printConfiguration(config); return printConfiguration(config);
} }
int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode) { int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode) {
return T55xxReadBlockEx(block, page1, usepwd, override, password, downlink_mode, false); return T55xxReadBlockEx(block, page1, usepwd, override, password, downlink_mode, true);
} }
int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, bool verbose) { int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, bool verbose) {

View file

@ -186,6 +186,12 @@ int CmdsParse(const command_t Commands[], const char *Cmd) {
dumpCommandsRecursive(Commands, 1); dumpCommandsRecursive(Commands, 1);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
if (strcmp(Cmd, "coffee") == 0) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, " ((\n ))\n" _YELLOW_(" .______.\n | |]\n \\ /\n `----´\n\n"));
return PM3_SUCCESS;
}
char cmd_name[128]; char cmd_name[128];
memset(cmd_name, 0, sizeof(cmd_name)); memset(cmd_name, 0, sizeof(cmd_name));

View file

@ -372,7 +372,7 @@ int ecdsa_signature_verify(mbedtls_ecp_group_id curveid, uint8_t *key_xy, uint8_
return res; return res;
} }
// take signature bytes, converts to ASN1 signature and tries to verify
int ecdsa_signature_r_s_verify(mbedtls_ecp_group_id curveid, uint8_t *key_xy, uint8_t *input, int length, uint8_t *r_s, size_t r_s_len, bool hash) { int ecdsa_signature_r_s_verify(mbedtls_ecp_group_id curveid, uint8_t *key_xy, uint8_t *input, int length, uint8_t *r_s, size_t r_s_len, bool hash) {
int res; int res;
uint8_t signature[MBEDTLS_ECDSA_MAX_LEN]; uint8_t signature[MBEDTLS_ECDSA_MAX_LEN];
@ -391,10 +391,8 @@ int ecdsa_signature_r_s_verify(mbedtls_ecp_group_id curveid, uint8_t *key_xy, ui
} }
res = ecdsa_signature_verify(curveid, key_xy, input, length, signature, signature_len, hash); res = ecdsa_signature_verify(curveid, key_xy, input, length, signature, signature_len, hash);
mbedtls_mpi_free(&r); mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s); mbedtls_mpi_free(&s);
return res; return res;
} }

View file

@ -1482,6 +1482,7 @@ static int filelist(const char *path, const char *ext, uint8_t last, bool tentat
char tmp_fullpath[1024] = {0}; char tmp_fullpath[1024] = {0};
strncat(tmp_fullpath, path, sizeof(tmp_fullpath) - 1); strncat(tmp_fullpath, path, sizeof(tmp_fullpath) - 1);
tmp_fullpath[1023] = 0x00;
strncat(tmp_fullpath, namelist[i]->d_name, strlen(tmp_fullpath) - 1); strncat(tmp_fullpath, namelist[i]->d_name, strlen(tmp_fullpath) - 1);
if (is_directory(tmp_fullpath)) { if (is_directory(tmp_fullpath)) {

View file

@ -535,7 +535,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
free(statelists[1].head.slhead); free(statelists[1].head.slhead);
num_to_bytes(key64, 6, resultKey); num_to_bytes(key64, 6, resultKey);
PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]", PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]",
package->block, package->block,
package->keytype ? 'B' : 'A', package->keytype ? 'B' : 'A',
sprint_hex(resultKey, 6) sprint_hex(resultKey, 6)
@ -714,7 +714,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
num_to_bytes(key64, 6, resultKey); num_to_bytes(key64, 6, resultKey);
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]", PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]",
package->block, package->block,
package->keytype ? 'B' : 'A', package->keytype ? 'B' : 'A',
sprint_hex(resultKey, 6) sprint_hex(resultKey, 6)
@ -959,7 +959,7 @@ int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid) {
} }
} }
int mfGen3Blk(uint8_t *block, int blockLen, uint8_t *newBlock) { int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_GEN3BLK, blockLen, 0, 0, block, 16); SendCommandMIX(CMD_HF_MIFARE_GEN3BLK, blockLen, 0, 0, block, 16);
PacketResponseNG resp; PacketResponseNG resp;
@ -974,7 +974,7 @@ int mfGen3Blk(uint8_t *block, int blockLen, uint8_t *newBlock) {
} }
} }
int mfGen3Freez(void) { int mfGen3Freeze(void) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_GEN3FREEZ, NULL, 0); SendCommandNG(CMD_HF_MIFARE_GEN3FREEZ, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
@ -1144,19 +1144,14 @@ int detect_classic_static_nonce(void) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_STATIC_NONCE, NULL, 0); SendCommandNG(CMD_HF_MIFARE_STATIC_NONCE, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_NONCE, &resp, 1000)) {
if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_NONCE, &resp, 500)) {
if (resp.status == PM3_ESOFT) if (resp.status == PM3_ESOFT)
return 2; return NONCE_FAIL;
if (resp.data.asBytes[0] == 0) return resp.data.asBytes[0];
return 0;
if (resp.data.asBytes[0] != 0)
return 1;
} }
return 2; return NONCE_FAIL;
} }
/* try to see if card responses to "chinese magic backdoor" commands. */ /* try to see if card responses to "chinese magic backdoor" commands. */
@ -1179,11 +1174,20 @@ int detect_classic_magic(void) {
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 1b")); PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 1b"));
break; break;
case MAGIC_GEN_2: case MAGIC_GEN_2:
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 2 / CUID")); PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 2 / CUID"));
break;
case MAGIC_GEN_3:
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 3 / APDU"));
break; break;
case MAGIC_GEN_UNFUSED: case MAGIC_GEN_UNFUSED:
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Write Once / FUID")); PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Write Once / FUID"));
break; break;
case MAGIC_SUPER:
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("super card"));
break;
case MAGIC_NTAG21X:
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("NTAG21x"));
break;
default: default:
break; break;
} }

View file

@ -81,8 +81,8 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params);
int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params);
int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid); int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid);
int mfGen3Blk(uint8_t *block, int blockLen, uint8_t *newBlock); int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock);
int mfGen3Freez(void); int mfGen3Freeze(void);
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);

View file

@ -53,6 +53,7 @@ extern bool showDemod;
#endif #endif
#define MAX_PRINT_BUFFER 2048 #define MAX_PRINT_BUFFER 2048
#define PROMPT_CLEARLINE PrintAndLogEx(INPLACE, " \r")
void PrintAndLogOptions(const char *str[][2], size_t size, size_t space); void PrintAndLogOptions(const char *str[][2], size_t size, size_t space);
void PrintAndLogEx(logLevel_t level, const char *fmt, ...); void PrintAndLogEx(logLevel_t level, const char *fmt, ...);
void SetFlushAfterWrite(bool value); void SetFlushAfterWrite(bool value);

View file

@ -591,7 +591,7 @@ static const cardformat_t FormatTable[] = {
{"H10306", Pack_H10306, Unpack_H10306, "HID H10306 34-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack {"H10306", Pack_H10306, Unpack_H10306, "HID H10306 34-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
{"N10002", Pack_N10002, Unpack_N10002, "HID N10002 34-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au {"N10002", Pack_N10002, Unpack_N10002, "HID N10002 34-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"C1k35s", Pack_C1k35s, Unpack_C1k35s, "HID Corporate 1000 35-bit standard layout", {1, 1, 0, 0, 1}}, // imported from old pack/unpack {"C1k35s", Pack_C1k35s, Unpack_C1k35s, "HID Corporate 1000 35-bit standard layout", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
{"C15001", Pack_C15001, Unpack_C15001, "HID KeySpan 36-bit", {1, 1, 0, 1, 1}}, // from Proxmark forums {"C15001", Pack_C15001, Unpack_C15001, "HID KeyScan 36-bit", {1, 1, 0, 1, 1}}, // from Proxmark forums
{"S12906", Pack_S12906, Unpack_S12906, "HID Simplex 36-bit", {1, 1, 1, 0, 1}}, // from cardinfo.barkweb.com.au {"S12906", Pack_S12906, Unpack_S12906, "HID Simplex 36-bit", {1, 1, 1, 0, 1}}, // from cardinfo.barkweb.com.au
{"Sie36", Pack_Sie36, Unpack_Sie36, "HID 36-bit Siemens", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au {"Sie36", Pack_Sie36, Unpack_Sie36, "HID 36-bit Siemens", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"H10320", Pack_H10320, Unpack_H10320, "HID H10320 36-bit BCD", {1, 0, 0, 0, 1}}, // from Proxmark forums {"H10320", Pack_H10320, Unpack_H10320, "HID H10320 36-bit BCD", {1, 0, 0, 0, 1}}, // from Proxmark forums

63
doc/cloner_notes.md Normal file
View file

@ -0,0 +1,63 @@
# Notes on Cloner gunes
This document is based mostly on information posted on http://www.proxmark.org/forum/viewtopic.php?pid=39903#p39903
- [Blue and black cloners](#blue-and-black-cloners)
- [White cloner (pre 2015)](#white-cloner-pre-2015)
- [White cloner (after 2016)](#white-cloner-after-2016)
- [White cloner (after 2016 D Quality)](#white-cloner-after-2016-d-quality)
- [restore page1 data](#restore-page1-data)
# Blue and black cloners
3 variants:
1. EM cloner
2. HID cloner
3. EM/HID cloner
Quality varies my manufacturer (Quality A (Good) until D (Bad))
They set a password on block 7 of the chip and set the password enable bit in block 0
```
Standard password is normally: 51243648
```
**Be sure to purchase the EM/HID version**
# White cloner (pre 2015)
Multifrequency
Buttons light up BLUE
Reads data correctly
Coil performance acceptable
```
Standard password is normally (for T55xx): AA55BBBB
Standard password 13,56mHz: individual per white cloner
```
# White cloner (after 2016)
Multifrequency
Buttons light up WHITE
Data scrambled (variable per individual cloner, possibly due to prevent legal issues)
Coil performance good
```
Standard password is normally (for T55xx): AA55BBBB
Standard password 13,56mHz: individual per white cloner
```
# White cloner (after 2016 D Quality)
Multifrequency (it says so but it doesn't)
Only works for EM/HID card (125kHz)
High frequency not working
```
Standard password is normally (for T55xx): AA55BBBB
```
**Note: Sets the HID card in TEST MODE**
# Restore page1 data
```
lf t55xx write b 1 d E0150A48 1
If t55xx write b 2 d 2D782308 1
```

844
doc/magic_cards_notes.md Normal file
View file

@ -0,0 +1,844 @@
# Notes on Magic Cards, aka UID changeable
This document is based mostly on information posted on http://www.proxmark.org/forum/viewtopic.php?pid=35372#p35372
Useful docs:
* [AN10833 MIFARE Type Identification Procedure](https://www.nxp.com/docs/en/application-note/AN10833.pdf)
- [ISO14443A](#iso14443a)
* [Identifying broken ISO14443A magic](#identifying-broken-iso14443a-magic)
- [MIFARE Classic](#mifare-classic)
* [MIFARE Classic block0](#mifare-classic-block0)
* [MIFARE Classic Gen1A aka UID](#mifare-classic-gen1a-aka-uid)
* [MIFARE Classic Gen1B](#mifare-classic-gen1b)
* [MIFARE Classic DirectWrite aka Gen2 aka CUID](#mifare-classic-directwrite-aka-gen2-aka-cuid)
* [MIFARE Classic DirectWrite, FUID version aka 1-write](#mifare-classic-directwrite-fuid-version-aka-1-write)
* [MIFARE Classic DirectWrite, UFUID version](#mifare-classic-directwrite-ufuid-version)
* [MIFARE Classic, other versions](#mifare-classic-other-versions)
* [MIFARE Classic APDU aka Gen3](#mifare-classic-apdu-aka-gen3)
* [MIFARE Classic Super](#mifare-classic-super)
- [MIFARE Ultralight](#mifare-ultralight)
* [MIFARE Ultralight blocks 0..2](#mifare-ultralight-blocks-02)
* [MIFARE Ultralight Gen1A](#mifare-ultralight-gen1a)
* [MIFARE Ultralight DirectWrite](#mifare-ultralight-directwrite)
* [MIFARE Ultralight EV1 DirectWrite](#mifare-ultralight-ev1-directwrite)
* [MIFARE Ultralight C Gen1A](#mifare-ultralight-c-gen1a)
* [MIFARE Ultralight C DirectWrite](#mifare-ultralight-c-directwrite)
- [NTAG](#ntag)
* [NTAG213 DirectWrite](#ntag213-directwrite)
* [NTAG21x](#ntag21x)
- [DESFire](#desfire)
* ["DESFire" APDU, 7b UID](#desfire-apdu-7b-uid)
* ["DESFire" APDU, 4b UID](#desfire-apdu-4b-uid)
- [ISO14443B](#iso14443b)
* [ISO14443B magic](#iso14443b-magic)
- [ISO15693](#iso15693)
* [ISO15693 magic](#iso15693-magic)
# ISO14443A
## Identifying broken ISO14443A magic
When a magic card configuration is really messed up and the card is not labeled, it may be hard to find out which type of card it is.
Here are some tips if the card doesn't react or gives error on a simple `hf 14a reader`:
Let's force a 4b UID anticollision and see what happens:
```
hf 14a config a 1 b 2 2 2 r 2
hf 14a reader
```
It it responds, we know it's a TypeA card. But maybe it's a 7b UID, so let's force a 7b UID anticollision:
```
hf 14a config a 1 b 2 2 1 3 2 r 2
hf 14a reader
```
At this stage, you know if it's a TypeA 4b or 7b card and you can check further on this page how to reconfigure different types of cards.
To restore anticollision config of the Proxmark3:
```
hf 14a config a 0 b 0 2 0 3 0 r 0
```
# MIFARE Classic
Referred as M1, S50 (1k), S70 (4k)
## MIFARE Classic block0
UID 4b: (actually NUID as there are no more "unique" IDs on 4b)
```
11223344440804006263646566676869
^^^^^^^^ UID
^^ BCC
^^ SAK(*)
^^^^ ATQA
^^^^^^^^^^^^^^^^ Manufacturer data
(*) some cards have a different SAK in their anticollision and in block0: +0x80 in the block0 (e.g. 08->88, 18->98)
```
Computing BCC on UID 11223344: `hf analyse lcr 11223344` = `44`
UID 7b:
```
04112233445566884400c82000000000
^^ Manufacturer byte
^^^^^^^^^^^^^^ UID
^^ SAK(*)
^^^^ ATQA
^^^^^^^^^^^^ Manufacturer data
(*) all? cards have a different SAK in their anticollision and in block0: +0x80 in the block0 (e.g. 08->88, 18->98)
```
## MIFARE Classic Gen1A aka UID
### Identify
```
hf 14a info
...
[+] Magic capabilities : Gen 1a
```
### Magic commands
* Wipe: `40(7)`, `41` (use 2000ms timeout)
* Read: `40(7)`, `43`, `30xx`+crc
* Write: `40(7)`, `43`, `A0xx`+crc, `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`+crc
### Characteristics
* UID: Only 4b versions
* ATQA:
* all cards play blindly the block0 ATQA bytes, beware!
* SAK:
* some cards play blindly the block0 SAK byte, beware!
* some cards use a fix "08" in anticollision, no matter the block0
* some cards use a fix "08" in anticollision, unless SAK in block0 has most significant bit "80" set, in which case SAK="88"
* BCC:
* all cards play blindly the block0 BCC byte, beware!
* ATS:
* no card with ATS
#### MIFARE Classic Gen1A flavour 1
* SAK: play blindly the block0 SAK byte, beware!
* PRNG: static 01200145
* Wipe: filled with 0xFF
#### MIFARE Classic Gen1A flavour 2
* SAK: play blindly the block0 SAK byte, beware!
* PRNG: static 01200145
* Wipe: filled with 0x00
#### MIFARE Classic Gen1A flavour 3
* SAK: 08
* PRNG: static 01200145
* Wipe: filled with 0xFF
#### MIFARE Classic Gen1A flavour 4
* SAK: 08
* PRNG: weak
* Wipe: timeout, no wipe
#### MIFARE Classic Gen1A flavour 5
* SAK: 08
* PRNG: weak
* Wipe: reply ok but no wipe performed
#### MIFARE Classic Gen1A flavour 6
* SAK: 08 or 88 if block0_SAK most significant bit is set
* PRNG: weak
* Wipe: timeout, no wipe
#### MIFARE Classic Gen1A flavour 7
* SAK: 08 or 88 if block0_SAK most significant bit is set
* PRNG: weak
* Wipe: filled with 0x00
### Proxmark3 commands
```
hf mf csetuid
hf mf cwipe
hf mf csetblk
hf mf cgetblk
hf mf cgetsc
hf mf cload
hf mf csave
hf mf cview
```
When "soft-bricked" (by writing invalid data in block0), these ones may help:
```
# MFC Gen1A 1k:
hf mf cwipe -u 11223344 -a 0004 -s 08
# MFC Gen1A 4k:
hf mf cwipe -u 11223344 -a 0044 -s 18
```
or just fixing block0:
```
# MFC Gen1A 1k:
hf mf csetuid 11223344 0004 08
# MFC Gen1A 4k:
hf mf csetuid 11223344 0044 18
```
```
script run remagic
```
To execute commands manually:
```
hf 14a raw -a -p -b 7 40
hf 14a raw -p 43
hf 14a raw -p -c A000
hf 14a raw -c -t 1000 11223344440804006263646566676869
```
wipe:
```
hf 14a raw -a -p -b 7 40
hf 14a raw -t 1000 41
```
### libnfc commands
```
nfc-mfsetuid
nfc-mfclassic R a u mydump
nfc-mfclassic W a u mydump
```
## MIFARE Classic Gen1B
Similar to Gen1A, but supports directly read/write after command 40
### Identify
```
hf 14a info
...
[+] Magic capabilities : Gen 1b
```
### Magic commands
* Read: `40(7)`, `30xx`
* Write: `40(7)`, `A0xx`+crc, `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`+crc
## MIFARE Classic DirectWrite aka Gen2 aka CUID
### Identify
```
hf 14a info
...
[+] Magic capabilities : Gen 2 / CUID
```
Not all Gen2 cards can be identified with `hf 14a info`, only those replying to RATS.
To identify the other ones, you've to try to write to block0 and see if it works...
### Magic commands
Android compatible
* issue regular write to block0
### Characteristics
* UID: 4b and 7b versions
* ATQA:
* some cards play blindly the block0 ATQA bytes, beware!
* some cards use a fix ATQA in anticollision, no matter the block0. Including all 7b.
* SAK:
* some cards play blindly the block0 SAK byte, beware!
* some cards use a fix "08" or "18" in anticollision, no matter the block0. Including all 7b.
* BCC:
* some cards play blindly the block0 BCC byte, beware!
* some cards compute a proper BCC in anticollision. Including all 7b comuting their BCC0 and BCC1.
* ATS:
* some cards don't reply to RATS
* some reply with an ATS
#### MIFARE Classic DirectWrite flavour 1
* UID 4b
* ATQA: play blindly the block0 ATQA bytes, beware!
* SAK: play blindly the block0 SAK byte, beware!
* BCC: play blindly the block0 BCC byte, beware!
* ATS: no
* PRNG: weak
#### MIFARE Classic DirectWrite flavour 2
* UID 4b
* ATQA: fixed
* SAK: fixed
* BCC: computed
* ATS: 0978009102DABC1910F005
* PRNG: weak
#### MIFARE Classic DirectWrite flavour 3
* UID 4b
* ATQA: play blindly the block0 ATQA bytes, beware!
* SAK: fixed
* BCC: play blindly the block0 BCC byte, beware!
* ATS: no
* PRNG: weak
#### MIFARE Classic DirectWrite flavour 4
* UID 7b
* ATQA: fixed
* SAK: fixed
* BCC: computed
* ATS: 0978009102DABC1910F005
* PRNG: static 00000000
#### MIFARE Classic DirectWrite flavour 5
* UID 4b
* ATQA: fixed
* SAK: play blindly the block0 SAK byte, beware!
* BCC: computed
* ATS: no
* PRNG: weak
#### MIFARE Classic DirectWrite flavour 6
**TODO** need more info
* UID 7b
* ATS: 0D780071028849A13020150608563D
### Proxmark3 commands
```
hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869
```
When "soft-bricked" (by writing invalid data in block0), these ones may help:
```
hf 14a config h
```
e.g. for 4b UID:
```
hf 14a config a 1 b 2 2 2 r 2
hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869 # for 1k
hf mf wrbl 0 A FFFFFFFFFFFF 11223344441802006263646566676869 # for 4k
hf 14a config a 0 b 0 2 0 r 0
hf 14a reader
```
e.g. for 7b UID:
```
hf 14a config a 1 b 2 2 1 3 2 r 2
hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566084400626364656667 # for 1k
hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566184200626364656667 # for 4k
hf 14a config a 0 b 0 2 0 3 0 r 0
hf 14a reader
```
## MIFARE Classic DirectWrite, FUID version aka 1-write
Same as MIFARE Classic DirectWrite, but block0 can be written only once.
Initial UID is AA55C396
### Identify
Only possible before personalisation.
```
hf 14a info
...
[+] Magic capabilities : Write Once / FUID
```
## MIFARE Classic DirectWrite, UFUID version
Same as MIFARE Classic DirectWrite, but block0 can be locked with special command.
### Identify
**TODO**
### Proxmark3 commands
To lock definitively block0:
```
hf 14a raw -a -p -b 7 40
hf 14a raw -p 43
hf 14a raw -p -c e000
hf 14a raw -c 85000000000000000000000000000008
```
## MIFARE Classic, other versions
**TODO**
* ZXUID, EUID, ICUID ?
* Some cards exhibit a specific SAK=28 ??
## MIFARE Classic APDU aka Gen3
### Identify
```
hf 14a info
...
[+] Magic capabilities : Gen 3 / APDU
```
### Magic commands
Android compatible
* issue special APDUs
```
cla ins p1 p2 len
90 F0 CC CC 10 <block0> - write block 0
90 FB CC CC 07 <uid> - change uid (independently of block0 data)
90 FD 11 11 00 - lock permanently
```
It seems the length byte gets ignored anyway.
Note: it seems some cards only accept the "change UID" command.
It accepts direct read of block0 (and only block0) without prior auth.
### Characteristics
* UID: 4b and 7b versions
* ATQA/SAK: fixed
* BCC: auto
* ATS: none
### Proxmark3 commands
```
# change just UID:
hf mf gen3uid
# write block0:
hf mf gen3blk
# lock (uid/block0?) forever:
hf mf gen3freeze
```
See also
```
script run mfc_gen3_writer -h
```
Equivalent:
```
# change just UID:
hf 14a raw -s -c -t 2000 90FBCCCC07 11223344556677
# write block0:
hf 14a raw -s -c -t 2000 90F0CCCC10 041219c3219316984200e32000000000
# lock (uid/block0?) forever:
hf 14a raw -s -c 90FD111100
```
## MIFARE Classic Super
It behaves like DirectWrite but records reader auth attempts.
To change UID: same commands as for MFC DirectWrite
To do reader-only attack: at least two versions exist.
* type 1: https://github.com/nfc-tools/nfc-supercard for card with ATS: 0978009102DABC1910F005
* type 2: https://github.com/netscylla/super-card/blob/master/libnfc-1.7.1/utils/nfc-super.c for ??
### Identify
Only type 1 at the moment:
```
hf 14a info
...
[+] Magic capabilities : super card
```
# MIFARE Ultralight
## MIFARE Ultralight blocks 0..2
```
SN0 SN1 SN2 BCC0
SN3 SN4 SN5 SN6
BCC1 Int LCK0 LCK1
```
UID is made of SN0..SN6 bytes
Computing BCC0 on UID 04112233445566: `analyse lcr 88041122` = `bf`
Computing BCC1 on UID 04112233445566: `analyse lcr 33445566` = `44`
Int is internal, typically 0x48
## MIFARE Ultralight Gen1A
### Identify
**TODO**
### Characteristics
#### Magic commands
**TODO**
#### UID
Only 7b versions
#### SAK, ATQA, BCC, ATS
**TODO** need more tests
### Proxmark3 commands
```
script run ul_uid -h
```
When "soft-bricked" (by writing invalid data in block0), these ones may help:
```
hf 14a config h
script run remagic -u
```
## MIFARE Ultralight DirectWrite
### Identify
```
hf 14a info
...
[+] Magic capabilities : Gen 2 / CUID
```
It seems so far that all MFUL DW have an ATS.
### Magic commands
Issue three regular MFU write commands in a row to write first three blocks.
### Characteristics
* UID: Only 7b versions
* ATQA:
* all cards play fix ATQA
* SAK:
* all cards play fix SAK
* BCC:
* some cards play blindly the block0 BCC0 and block2 BCC1 bytes, beware!
* some cards compute proper BCC0 and BCC1 in anticollision
* ATS:
* all cards reply with an ATS
#### MIFARE Ultralight DirectWrite flavour 1
* BCC: computed
* ATS: 0A78008102DBA0C119402AB5
#### MIFARE Ultralight DirectWrite flavour 2
* BCC: play blindly the block0 BCC0 and block2 BCC1 bytes, beware!
* ATS: 850000A00A000AB00000000000000000184D
### Proxmark3 commands
```
hf mfu setuid
```
Equivalent: don't use `hf mfu wrbl` as you need to write three blocks in a row, but do, with proper BCCx:
```
hf 14a raw -s -c -p a2 00 041122bf
hf 14a raw -c -p a2 01 33445566
hf 14a raw -c a2 02 44480000
```
When "soft-bricked" (by writing invalid data in block0), these ones may help:
```
hf 14a config h
```
E.g.:
```
hf 14a config a 1 b 2 2 1 3 2 r 2
hf mfu setuid 04112233445566
hf 14a config a 0 b 0 2 0 3 0 r 0
hf 14a reader
```
### libnfc commands
```
nfc-mfultralight -h
```
See `--uid` and `--full`
### Android
* MIFARE++ Ultralight
## MIFARE Ultralight EV1 DirectWrite
Similar to MFUL DirectWrite
### Identify
```
hf 14a info
...
[+] Magic capabilities : Gen 2 / CUID
```
### Characteristics
* UID: Only 7b versions
* ATQA:
* all cards play fix ATQA
* SAK:
* all cards play fix SAK
* BCC:
* cards play blindly the block0 BCC0 and block2 BCC1 bytes, beware!
* ATS:
* all cards reply with an ATS
#### MIFARE Ultralight EV1 DirectWrite flavour 1
* BCC: play blindly the block0 BCC0 and block2 BCC1 bytes, beware!
* ATS: 850000A000000AC30004030101000B0341DF
#### MIFARE Ultralight EV1 DirectWrite flavour 2
* BCC: play blindly the block0 BCC0 and block2 BCC1 bytes, beware!
* ATS: 850000A00A000AC30004030101000B0316D7
## MIFARE Ultralight C Gen1A
Similar to MFUL Gen1A
## MIFARE Ultralight C DirectWrite
Similar to MFUL DirectWrite
### Identify
```
hf 14a info
...
[+] Magic capabilities : Gen 2 / CUID
```
### Characteristics
* UID: Only 7b versions
* ATQA:
* all cards play fix ATQA
* SAK:
* all cards play fix SAK
* BCC:
* cards compute proper BCC0 and BCC1 in anticollision
* ATS:
* all cards reply with an ATS
#### MIFARE Ultralight C DirectWrite flavour 1
* BCC: computed
* ATS: 0A78008102DBA0C119402AB5
# NTAG
## NTAG213 DirectWrite
Similar to MFUL DirectWrite
### Identify
```
hf 14a info
...
[+] Magic capabilities : Gen 2 / CUID
```
### Characteristics
* UID: Only 7b versions
* ATQA:
* all cards play fix ATQA
* SAK:
* all cards play fix SAK
* BCC:
* cards play blindly the block0 BCC0 and block2 BCC1 bytes, beware!
* ATS:
* all cards reply with an ATS
#### NTAG213 DirectWrite flavour 1
* BCC: play blindly the block0 BCC0 and block2 BCC1 bytes, beware!
* ATS: 0A78008102DBA0C119402AB5
## NTAG21x
### Identify
```
hf 14a info
...
[+] Magic capabilities : NTAG21x
```
### Characteristics
Emulates fully NTAG213, 213F, 215, 216, 216F
Emulates partially UL EV1 48k/128k, NTAG210, NTAG212, NTAGI2C 1K/2K, NTAGI2C 1K/2K PLUS
### Proxmark3 commands
```
script run mfu_magic -h
```
# DESFire
## "DESFire" APDU, 7b UID
### Identify
**TODO**
### Magic commands
Android compatible
* issue special APDUs
### Characteristics
* ATQA: 0344
* SAK: 20
* ATS: 0675338102005110 or 06757781028002F0
Only mimics DESFire anticollision (but wrong ATS), no further DESFire support
### Proxmark commands
UID 04112233445566
```
hf 14a raw -s -c 0200ab00000704112233445566
```
or equivalently
```
hf 14a apdu -s 00ab00000704112233445566
```
### libnfc commands
```
pn53x-tamashell
4a0100
420200ab00000704112233445566
```
## "DESFire" APDU, 4b UID
### Magic commands
Android compatible
* issue special APDUs
### Characteristics
* ATQA: 0008 ??? This is not DESFire, 0008/20 doesn't match anything
* SAK: 20
* ATS: 0675338102005110 or 06757781028002F0
Only mimics DESFire anticollision (but wrong ATS), no further DESFire support
### Proxmark commands
UID 04112233445566
```
hf 14a raw -s -c 0200ab00000411223344
```
or equivalently
```
hf 14a apdu -s 00ab00000411223344
```
It accepts longer UID but that doesn't affect BCC/ATQA/SAK
### pn53x-tamashell commands
```
4a0100
420200ab00000411223344
```
### Remarks
The same effect (with better ATQA!) can be obtained with a MFC Gen1A that uses SAK defined in block0:
```
hf mf csetblk 0 1122334444204403A1A2A3A4A5A6A7A8
hf 14a info
[+] UID: 11 22 33 44
[+] ATQA: 03 44
[+] SAK: 20 [1]
[+] Possible types:
[+] MIFARE DESFire MF3ICD40
```
# ISO14443B
## ISO14443B magic
No such card is available.
Some vendor allow to specify an ID (PUPI) when ordering a card.
# ISO15693
## ISO15693 magic
### Identify
**TODO**
### Proxmark3 commands
Always set a UID starting with `E0`.
```
hf 15 csetuid E011223344556677
```
or (ignore errors):
```
script run iso15_magic -u E004013344556677
```

View file

@ -17,12 +17,10 @@ There are two ways to install, build and use Proxmark3 on Windows:
Install required drivers for your Windows installation. You may need admin privileges to do this. Install required drivers for your Windows installation. You may need admin privileges to do this.
Step by step guides are online such as [RyscCorps](https://store.ryscc.com/blogs/news/how-to-install-a-proxmark3-driver-on-windows-10). Step by step guides are online such as [RyscCorps](https://store.ryscc.com/blogs/news/how-to-install-a-proxmark3-driver-on-windows-10).
## Download / clone ProxSpace repo ## Download ProxSpace repo
Download the Gator96100 ProxSpace package from https://github.com/Gator96100/ProxSpace/releases Download the Gator96100 ProxSpace package from https://github.com/Gator96100/ProxSpace/releases
If you prefer, you can clone it, provided that you installed Github for Windows https://desktop.github.com/.
Extract 'ProxSpace' to a location path without spaces. Extract 'ProxSpace' to a location path without spaces.
For example D:\OneDrive\Documents\GitHub is ok whereas C:\My Documents\My Projects\proxspace is not. For example D:\OneDrive\Documents\GitHub is ok whereas C:\My Documents\My Projects\proxspace is not.
@ -30,7 +28,7 @@ If you're running Windows in a Virtualbox guest, make sure not to install ProxSp
## Launch ProxSpace ## Launch ProxSpace
Run `runme.bat` or `runme64.bat` depending on your Windows architecture. Run `runme64.bat`.
You'll get a Bash prompt and your home directory should become the ProxSpace `pm3` sub-directory. You'll get a Bash prompt and your home directory should become the ProxSpace `pm3` sub-directory.
@ -76,8 +74,15 @@ If you want to run the graphical components of the Proxmark3 client, you need to
Enter WSL prompt (`wsl`) and from there, follow the [Linux Installation Instructions](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) for Ubuntu, summarized here below: Enter WSL prompt (`wsl`) and from there, follow the [Linux Installation Instructions](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) for Ubuntu, summarized here below:
Make sure your WSL guest OS is up-to-date first
```sh ```sh
sudo apt-get update sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get auto-remove -y
```
Install dependencies
```sh
sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \ sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \
libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev qtbase5-dev libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev qtbase5-dev
``` ```

View file

@ -24,6 +24,13 @@ git pull
make clean && make all make clean && make all
``` ```
### if you got an error
Read the [troubleshooting guide](/doc/md/Installation_Instructions/Troubleshooting.md),
For instance, on WSl-1 you usually get the _libQt5Core.so.5 not found_ message
[solution](/doc/md/Installation_Instructions/Troubleshooting.md#libQt5Coreso5-not-found)
## Install ## Install
This is an optional step. If you do This is an optional step. If you do

View file

@ -710,6 +710,11 @@ typedef struct {
#define MODE_EXIT_AFTER_MAC 1 #define MODE_EXIT_AFTER_MAC 1
#define MODE_FULLSIM 2 #define MODE_FULLSIM 2
// Static Nonce detection
#define NONCE_FAIL 0x01
#define NONCE_NORMAL 0x02
#define NONCE_STATIC 0x03
// Dbprintf flags // Dbprintf flags
#define FLAG_RAWPRINT 0x00 #define FLAG_RAWPRINT 0x00
#define FLAG_LOG 0x01 #define FLAG_LOG 0x01

View file

@ -215,10 +215,13 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define MAGIC_SINGLE (MAGIC_WUPC | MAGIC_HALT | MAGIC_INIT | MAGIC_OFF) //0x1E #define MAGIC_SINGLE (MAGIC_WUPC | MAGIC_HALT | MAGIC_INIT | MAGIC_OFF) //0x1E
// by CMD_HF_MIFARE_CIDENT // by CMD_HF_MIFARE_CIDENT
#define MAGIC_GEN_1A 1 #define MAGIC_GEN_1A 1
#define MAGIC_GEN_1B 2 #define MAGIC_GEN_1B 2
#define MAGIC_GEN_2 4 #define MAGIC_GEN_2 4
#define MAGIC_GEN_UNFUSED 5 #define MAGIC_GEN_UNFUSED 5
#define MAGIC_SUPER 6
#define MAGIC_NTAG21X 7
#define MAGIC_GEN_3 8
/** /**
06 00 = INITIATE 06 00 = INITIATE
0E xx = SELECT ID (xx = Chip-ID) 0E xx = SELECT ID (xx = Chip-ID)

View file

@ -348,7 +348,9 @@ while true; do
if ! CheckExecute "lf VIKING test" "$CLIENTBIN -c 'data load traces/Transit999-best.pm3;lf search 1'" "Viking ID found"; then break; fi if ! CheckExecute "lf VIKING test" "$CLIENTBIN -c 'data load traces/Transit999-best.pm3;lf search 1'" "Viking ID found"; then break; fi
if ! CheckExecute "lf FDX-B test" "$CLIENTBIN -c 'data load traces/homeagain1600.pm3;lf search 1'" "FDX-B ID found"; then break; fi if ! CheckExecute "lf FDX-B test" "$CLIENTBIN -c 'data load traces/homeagain1600.pm3;lf search 1'" "FDX-B ID found"; then break; fi
if ! CheckExecute "lf INDALA test" "$CLIENTBIN -c 'data load traces/indala-504278295.pm3;lf search 1'" "Indala ID found"; then break; fi if ! CheckExecute "lf INDALA test" "$CLIENTBIN -c 'data load traces/indala-504278295.pm3;lf search 1'" "Indala ID found"; then break; fi
if ! CheckExecute "lf FDX/BioThermo test" "$CLIENTBIN -c 'data load traces/lf_fdx_biothermo.pm3; lf fdx demo'" "95.2 F / 35.1 C"; then break; fi if ! CheckExecute "lf FDX/BioThermo test" "$CLIENTBIN -c 'data load traces/lf_fdx_biothermo.pm3; lf fdx demod'" "95.2 F / 35.1 C"; then break; fi
if ! CheckExecute "lf GPROXII test" "$CLIENTBIN -c 'data load traces/lf_gprox_36_30_14489.pm3; lf search 1'" "Guardall G-Prox II ID found"; then break; fi
if ! CheckExecute "lf IDTECK test" "$CLIENTBIN -c 'data load traces/lf_idteck_4944544BAC40E069.pm3; lf search 1'" "Idteck ID found"; then break; fi
echo -e "\n${C_BLUE}Testing HF:${C_NC}" echo -e "\n${C_BLUE}Testing HF:${C_NC}"
if ! CheckExecute "hf mf offline text" "$CLIENTBIN -c 'hf mf'" "at_enc"; then break; fi if ! CheckExecute "hf mf offline text" "$CLIENTBIN -c 'hf mf'" "at_enc"; then break; fi

View file

@ -13,6 +13,8 @@ indala-504278295.pm3: PSK 26 bit indala
homeagain.pm3: HomeAgain animal (cat) tag - ID 985121004515220 homeagain.pm3: HomeAgain animal (cat) tag - ID 985121004515220
homeagain1600.pm3: HomeAgain animal (cat) tag - ID 985121004515220 homeagain1600.pm3: HomeAgain animal (cat) tag - ID 985121004515220
keri.pm3: Keri PSK-3 Key Ring tag (back of tag: 1460 3411) keri.pm3: Keri PSK-3 Key Ring tag (back of tag: 1460 3411)
lf_gprox_36_30_14489.pm3: G-Prox-II FC: 30 Card: 3949, Format 36b ASK/BIPHASE
lf_idteck_4944544BAC40E069.pm3: IDTECK raw 4944544BAC40E069 , PSK
Transit999-best.pm3: Transit 999 format (UID 99531670) Transit999-best.pm3: Transit 999 format (UID 99531670)
ATA5577-HIDemu-FC1-C9.pm3: ata5577 in hid prox 26 bit emulation facility code:1 card#:9 ATA5577-HIDemu-FC1-C9.pm3: ata5577 in hid prox 26 bit emulation facility code:1 card#:9
AWID-15-259.pm3: AWID FSK RF/50 FC: 15 Card: 259 AWID-15-259.pm3: AWID FSK RF/50 FC: 15 Card: 259

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff