mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-26 02:06:13 +08:00
commit
ce61d78425
202
appveyor.yml
202
appveyor.yml
|
@ -1,13 +1,17 @@
|
||||||
version: 3.0.1.{build}
|
version: 3.0.1.{build}
|
||||||
image: Visual Studio 2019
|
image: Visual Studio 2019
|
||||||
clone_folder: C:\ProxSpace\pm3\proxmark
|
clone_folder: C:\ProxSpace\pm3\proxmark
|
||||||
|
cache:
|
||||||
|
- C:\cache -> appveyor.yml
|
||||||
environment:
|
environment:
|
||||||
proxspace_url: https://github.com/Gator96100/ProxSpace/archive/master.zip
|
proxspace_url: https://github.com/Gator96100/ProxSpace/archive/master.zip
|
||||||
proxspace_zip_file: \proxspace.zip
|
proxspace_zip_file: \proxspace.zip
|
||||||
proxspace_zip_folder_name: ProxSpace-*
|
proxspace_zip_folder_name: ProxSpace-*
|
||||||
proxspace_path: \ProxSpace
|
proxspace_path: C:\ProxSpace
|
||||||
proxspace_home_path: \ProxSpace\pm3
|
proxspace_home_path: \ProxSpace\pm3
|
||||||
|
proxspace_cache_path: C:\cache
|
||||||
wsl_git_path: C:\proxmark
|
wsl_git_path: C:\proxmark
|
||||||
|
APPVEYOR_SAVE_CACHE_ON_ERROR: true
|
||||||
|
|
||||||
init:
|
init:
|
||||||
- ps: >-
|
- ps: >-
|
||||||
|
@ -34,39 +38,19 @@ init:
|
||||||
clone_script:
|
clone_script:
|
||||||
- ps: >-
|
- ps: >-
|
||||||
|
|
||||||
Function ExecUpdate($Text, $firstStart) {
|
Function GitClone($Text, $Folder) {
|
||||||
Write-Host "$Text"
|
Write-Host "$Text" -NoNewLine
|
||||||
Start-Process "cmd.exe" "/c ""cd /D $env:proxspace_path && runme64.bat -c ""exit"""""
|
if(-not $env:appveyor_pull_request_number) {
|
||||||
$StartTime=[System.Environment]::TickCount
|
git clone -q --branch=$env:appveyor_repo_branch https://github.com/$env:appveyor_repo_name.git $Folder
|
||||||
Start-Sleep -s 10
|
cd $Folder
|
||||||
while($true) {
|
git checkout -qf $env:appveyor_repo_commit
|
||||||
$cmdprocess = Get-Process "cmd" -ErrorAction SilentlyContinue
|
} else {
|
||||||
|
git clone -q https://github.com/$env:appveyor_repo_name.git $Folder
|
||||||
if (!$cmdprocess -Or $cmdprocess.HasExited) {
|
cd $Folder
|
||||||
Write-Host "$Text" -NoNewLine
|
git fetch -q origin +refs/pull/$env:appveyor_pull_request_number/merge:
|
||||||
Write-Host "[ OK ]" -ForegroundColor Green
|
git checkout -qf FETCH_HEAD
|
||||||
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 "$Text" -NoNewLine
|
|
||||||
Write-Host "Exit by pacman.conf" -ForegroundColor Green
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([System.Environment]::TickCount-$StartTime -gt 1000000) {
|
|
||||||
Write-Host "$Text" -NoNewLine
|
|
||||||
Write-host "Exit by timeout" -ForegroundColor Yellow
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
Start-Sleep -s 5
|
|
||||||
Receive-Job -Job $WSLjob
|
|
||||||
}
|
}
|
||||||
|
Write-Host "[ OK ]" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
|
|
||||||
$WSLjob = Start-Job -Name WSLInstall -ScriptBlock {
|
$WSLjob = Start-Job -Name WSLInstall -ScriptBlock {
|
||||||
|
@ -86,6 +70,94 @@ clone_script:
|
||||||
Add-AppveyorMessage -Message "WSL setup took $(([System.Environment]::TickCount-$WSLInstallTime) / 1000) sec" -Category Information
|
Add-AppveyorMessage -Message "WSL setup took $(([System.Environment]::TickCount-$WSLInstallTime) / 1000) sec" -Category Information
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$env:PSInstallTime=[System.Environment]::TickCount
|
||||||
|
|
||||||
|
Write-Host "ProxSpace: Removing folder..." -NoNewLine
|
||||||
|
|
||||||
|
cd \
|
||||||
|
|
||||||
|
Remove-Item -Recurse -Force -Path $env:proxspace_path -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
Write-Host "[ OK ]" -ForegroundColor Green
|
||||||
|
|
||||||
|
Write-Host "ProxSpace: downloading..." -NoNewLine
|
||||||
|
|
||||||
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
|
||||||
|
Invoke-WebRequest "$env:proxspace_url" -outfile "$env:proxspace_zip_file"
|
||||||
|
|
||||||
|
Write-Host "[ OK ]" -ForegroundColor Green
|
||||||
|
|
||||||
|
Write-Host "ProxSpace: extracting..." -NoNewLine
|
||||||
|
|
||||||
|
Expand-Archive -LiteralPath "$env:proxspace_zip_file" -DestinationPath "\"
|
||||||
|
|
||||||
|
Remove-Item "$env:proxspace_zip_file"
|
||||||
|
|
||||||
|
Write-Host "[ OK ]" -ForegroundColor Green
|
||||||
|
|
||||||
|
Write-Host "ProxSpace: renaming folder..." -NoNewLine
|
||||||
|
|
||||||
|
Get-ChildItem -Path "\$env:proxspace_zip_folder_name" | Rename-Item -NewName (Split-Path $env:proxspace_path -Leaf)
|
||||||
|
|
||||||
|
Write-Host "[ OK ]" -ForegroundColor Gree
|
||||||
|
|
||||||
|
$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
|
||||||
|
|
||||||
|
GitClone "ProxSpace: Cloning repository <$env:appveyor_repo_name> to $env:appveyor_build_folder ..." $env:appveyor_build_folder
|
||||||
|
|
||||||
|
GitClone "WSL: Cloning repository <$env:appveyor_repo_name> to $env:wsl_git_path ..." $env:wsl_git_path
|
||||||
|
|
||||||
|
|
||||||
|
install:
|
||||||
|
- ps: >-
|
||||||
|
|
||||||
|
Function ExecUpdate($Text, $firstStart) {
|
||||||
|
Write-Host "$Text"
|
||||||
|
|
||||||
|
$PSjob = Start-Job -Name PSInstall -ScriptBlock {
|
||||||
|
cd $env:proxspace_path
|
||||||
|
./runme64.bat -c "exit"
|
||||||
|
}
|
||||||
|
|
||||||
|
$StartTime=[System.Environment]::TickCount
|
||||||
|
Start-Sleep -s 10
|
||||||
|
while($true) {
|
||||||
|
if ($PSjob.State -eq 'Completed') {
|
||||||
|
Write-Host "$Text" -NoNewLine
|
||||||
|
Write-Host "[ OK ]" -ForegroundColor Green
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PSjob.State -eq 'Failed') {
|
||||||
|
Write-Host "$Text" -NoNewLine
|
||||||
|
Write-Host "[ Failed ]" -ForegroundColor Red
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($firstStart -And (Test-Path "$env:proxspace_path\msys2\etc\pacman.conf.pacnew")) {
|
||||||
|
Start-Sleep -s 5
|
||||||
|
Stop-Job -Job $PSjob
|
||||||
|
Start-Sleep -s 5
|
||||||
|
Write-Host "$Text" -NoNewLine
|
||||||
|
Write-Host "Exit by pacman.conf" -ForegroundColor Green
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([System.Environment]::TickCount-$StartTime -gt 1000000) {
|
||||||
|
Stop-Job -Job $PSjob
|
||||||
|
Write-Host "$Text" -NoNewLine
|
||||||
|
Write-host "Exit by timeout" -ForegroundColor Yellow
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Sleep -s 5
|
||||||
|
Receive-Job -Name WSLInstall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Function GitClone($Text, $Folder) {
|
Function GitClone($Text, $Folder) {
|
||||||
Write-Host "$Text" -NoNewLine
|
Write-Host "$Text" -NoNewLine
|
||||||
if(-not $env:appveyor_pull_request_number) {
|
if(-not $env:appveyor_pull_request_number) {
|
||||||
|
@ -101,41 +173,9 @@ clone_script:
|
||||||
Write-Host "[ OK ]" -ForegroundColor Green
|
Write-Host "[ OK ]" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "ProxSpace: Removing folder..." -NoNewLine
|
Write-Host "ProxSpace: move cache..." -NoNewLine
|
||||||
|
|
||||||
$PSInstallTime=[System.Environment]::TickCount
|
Move-Item -Path "$env:proxspace_cache_path" -Destination "$env:proxspace_path\msys2\var\cache" -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
cd \
|
|
||||||
|
|
||||||
Remove-Item -Recurse -Force -Path $env:proxspace_path
|
|
||||||
|
|
||||||
Write-Host "[ OK ]" -ForegroundColor Green
|
|
||||||
|
|
||||||
Receive-Job -Job $WSLjob
|
|
||||||
|
|
||||||
Write-Host "ProxSpace: downloading..." -NoNewLine
|
|
||||||
|
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
||||||
|
|
||||||
Invoke-WebRequest "$env:proxspace_url" -outfile "$env:proxspace_zip_file"
|
|
||||||
|
|
||||||
Write-Host "[ OK ]" -ForegroundColor Green
|
|
||||||
|
|
||||||
Receive-Job -Job $WSLjob
|
|
||||||
|
|
||||||
Write-Host "ProxSpace: extracting..." -NoNewLine
|
|
||||||
|
|
||||||
Expand-Archive -LiteralPath "$env:proxspace_zip_file" -DestinationPath "\"
|
|
||||||
|
|
||||||
Remove-Item "$env:proxspace_zip_file"
|
|
||||||
|
|
||||||
Write-Host "[ OK ]" -ForegroundColor Green
|
|
||||||
|
|
||||||
Receive-Job -Job $WSLjob
|
|
||||||
|
|
||||||
Write-Host "ProxSpace: renaming folder..." -NoNewLine
|
|
||||||
|
|
||||||
Get-ChildItem -Path "\$env:proxspace_zip_folder_name" | Rename-Item -NewName (Split-Path $env:proxspace_path -Leaf)
|
|
||||||
|
|
||||||
Write-Host "[ OK ]" -ForegroundColor Gree
|
Write-Host "[ OK ]" -ForegroundColor Gree
|
||||||
|
|
||||||
|
@ -143,21 +183,8 @@ clone_script:
|
||||||
|
|
||||||
ExecUpdate "ProxSpace: installing required packages..." $false
|
ExecUpdate "ProxSpace: installing required packages..." $false
|
||||||
|
|
||||||
|
Add-AppveyorMessage -Message "ProxSpace download and update took $(([System.Environment]::TickCount-$env:PSInstallTime) / 1000) sec" -Category Information
|
||||||
|
|
||||||
$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
|
|
||||||
|
|
||||||
Add-AppveyorMessage -Message "ProxSpace download and update took $(([System.Environment]::TickCount-$PSInstallTime) / 1000) sec" -Category Information
|
|
||||||
|
|
||||||
GitClone "ProxSpace: Cloning repository <$env:appveyor_repo_name> to $env:appveyor_build_folder ..." $env:appveyor_build_folder
|
|
||||||
|
|
||||||
Receive-Job -Wait -Job $WSLjob
|
|
||||||
|
|
||||||
GitClone "WSL: Cloning repository <$env:appveyor_repo_name> to $env:wsl_git_path ..." $env:wsl_git_path
|
|
||||||
|
|
||||||
|
|
||||||
install:
|
|
||||||
build_script:
|
build_script:
|
||||||
- ps: >-
|
- ps: >-
|
||||||
|
|
||||||
|
@ -203,6 +230,9 @@ build_script:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#WSL: wait for installation to finish
|
||||||
|
Receive-Job -Wait -Name WSLInstall
|
||||||
|
|
||||||
#Windows Subsystem for Linux (WSL)
|
#Windows Subsystem for Linux (WSL)
|
||||||
Write-Host "---------- WSL make ----------" -ForegroundColor Yellow
|
Write-Host "---------- WSL make ----------" -ForegroundColor Yellow
|
||||||
cd $env:wsl_git_path
|
cd $env:wsl_git_path
|
||||||
|
@ -234,6 +264,16 @@ build_script:
|
||||||
|
|
||||||
#ProxSpace
|
#ProxSpace
|
||||||
|
|
||||||
|
Write-Host "ProxSpace: create new cache..." -NoNewLine
|
||||||
|
|
||||||
|
ExecMinGWCmd 'yes | pacman -Sc > /dev/null 2>&1'
|
||||||
|
|
||||||
|
Remove-Item -Recurse -Force -Path "$env:proxspace_cache_path" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
Move-Item -Path "$env:proxspace_path\msys2\var\cache" -Destination "$env:proxspace_cache_path" -Force
|
||||||
|
|
||||||
|
Write-Host "[ OK ]" -ForegroundColor Gree
|
||||||
|
|
||||||
Write-Host "---------- PS make ----------" -ForegroundColor Yellow
|
Write-Host "---------- PS make ----------" -ForegroundColor Yellow
|
||||||
|
|
||||||
$TestTime=[System.Environment]::TickCount
|
$TestTime=[System.Environment]::TickCount
|
||||||
|
|
|
@ -118,7 +118,7 @@ static int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response, uint16_t re
|
||||||
case 'a':
|
case 'a':
|
||||||
return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
|
return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
|
||||||
case 'b':
|
case 'b':
|
||||||
return iso14443b_apdu(apdu, length, false, response, respmaxlen);
|
return iso14443b_apdu(apdu, length, false, response, respmaxlen, NULL);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len) {
|
||||||
|
|
||||||
optimizedSniff((uint16_t *)mem, *len);
|
optimizedSniff((uint16_t *)mem, *len);
|
||||||
|
|
||||||
if (DBGLEVEL >= DBG_INFO) {
|
if (DBGLEVEL >= DBG_INFO) {
|
||||||
Dbprintf("Trigger kicked in (%d >= 180)", r);
|
Dbprintf("Trigger kicked in (%d >= 180)", r);
|
||||||
Dbprintf("Collected %u samples", *len);
|
Dbprintf("Collected %u samples", *len);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2687,7 +2687,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
|
||||||
SpinDelay(100);
|
SpinDelay(50);
|
||||||
|
|
||||||
// Start the timer
|
// Start the timer
|
||||||
StartCountSspClk();
|
StartCountSspClk();
|
||||||
|
|
|
@ -784,6 +784,7 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
||||||
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
|
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
|
||||||
if (((ABS(Demod.sumI) > ABS(Demod.sumQ)) && (((ci > 0) && (Demod.sumI > 0)) || ((ci < 0) && (Demod.sumI < 0)))) || // signal closer to horizontal, polarity check based on on I
|
if (((ABS(Demod.sumI) > ABS(Demod.sumQ)) && (((ci > 0) && (Demod.sumI > 0)) || ((ci < 0) && (Demod.sumI < 0)))) || // signal closer to horizontal, polarity check based on on I
|
||||||
((ABS(Demod.sumI) <= ABS(Demod.sumQ)) && (((cq > 0) && (Demod.sumQ > 0)) || ((cq < 0) && (Demod.sumQ < 0))))) { // signal closer to vertical, polarity check based on on Q
|
((ABS(Demod.sumI) <= ABS(Demod.sumQ)) && (((cq > 0) && (Demod.sumQ > 0)) || ((cq < 0) && (Demod.sumQ < 0))))) { // signal closer to vertical, polarity check based on on Q
|
||||||
|
|
||||||
if (Demod.posCount < 10) { // refine signal approximation during first 10 samples
|
if (Demod.posCount < 10) { // refine signal approximation during first 10 samples
|
||||||
Demod.sumI += ci;
|
Demod.sumI += ci;
|
||||||
Demod.sumQ += cq;
|
Demod.sumQ += cq;
|
||||||
|
@ -1103,7 +1104,7 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
|
||||||
|
|
||||||
// Send SOF
|
// Send SOF
|
||||||
// 10-11 ETUs of ZERO
|
// 10-11 ETUs of ZERO
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 11; i++) {
|
||||||
tosend_stuffbit(0);
|
tosend_stuffbit(0);
|
||||||
}
|
}
|
||||||
// 2-3 ETUs of ONE
|
// 2-3 ETUs of ONE
|
||||||
|
@ -1132,23 +1133,21 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
|
||||||
// EGT extra guard time 1 ETU = 9us
|
// EGT extra guard time 1 ETU = 9us
|
||||||
// For PCD it ranges 0-57us === 0 - 6 ETU
|
// For PCD it ranges 0-57us === 0 - 6 ETU
|
||||||
// FOR PICC it ranges 0-19us == 0 - 2 ETU
|
// FOR PICC it ranges 0-19us == 0 - 2 ETU
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send EOF
|
// Send EOF
|
||||||
// 10-11 ETUs of ZERO
|
// 10-11 ETUs of ZERO
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 11; i++) {
|
||||||
tosend_stuffbit(0);
|
tosend_stuffbit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tosend_stuffbit(1);
|
|
||||||
/* Transition time. TR0 - guard time
|
/* Transition time. TR0 - guard time
|
||||||
* TR0 - 8 ETU's minimum.
|
* TR0 - 8 ETU's minimum.
|
||||||
* TR0 - 32 ETU's maximum for ATQB only
|
* TR0 - 32 ETU's maximum for ATQB only
|
||||||
* TR0 - FWT for all other commands
|
* TR0 - FWT for all other commands
|
||||||
* 32,64,128,256,512, ... , 262144, 524288 ETU
|
* 32,64,128,256,512, ... , 262144, 524288 ETU
|
||||||
*/
|
*/
|
||||||
int pad = (12 + (len * 10) + 11) & 0x7;
|
int pad = (11 + 2 + (len * 10) + 11) & 0x7;
|
||||||
|
|
||||||
for (i = 0; i < 16 - pad; ++i)
|
for (i = 0; i < 16 - pad; ++i)
|
||||||
tosend_stuffbit(1);
|
tosend_stuffbit(1);
|
||||||
|
@ -1168,7 +1167,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t
|
||||||
/* Sends an APDU to the tag
|
/* Sends an APDU to the tag
|
||||||
* TODO: check CRC and preamble
|
* TODO: check CRC and preamble
|
||||||
*/
|
*/
|
||||||
int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, uint8_t *response, uint16_t respmaxlen) {
|
int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *res) {
|
||||||
|
|
||||||
uint8_t real_cmd[msg_len + 4];
|
uint8_t real_cmd[msg_len + 4];
|
||||||
|
|
||||||
|
@ -1195,10 +1194,10 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, uint8
|
||||||
CodeAndTransmit14443bAsReader(real_cmd, msg_len + 3, &start_time, &eof_time);
|
CodeAndTransmit14443bAsReader(real_cmd, msg_len + 3, &start_time, &eof_time);
|
||||||
|
|
||||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||||
int len = Get14443bAnswerFromTag(response, respmaxlen, ISO14443B_READER_TIMEOUT, &eof_time);
|
int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, ISO14443B_READER_TIMEOUT, &eof_time);
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
|
|
||||||
uint8_t *data_bytes = (uint8_t *) response;
|
uint8_t *data_bytes = (uint8_t *) rxdata;
|
||||||
|
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
return 0; //DATA LINK ERROR
|
return 0; //DATA LINK ERROR
|
||||||
|
@ -1219,10 +1218,10 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, uint8
|
||||||
|
|
||||||
// retrieve the result again (with increased timeout)
|
// retrieve the result again (with increased timeout)
|
||||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||||
len = Get14443bAnswerFromTag(response, respmaxlen, ISO14443B_READER_TIMEOUT, &eof_time);
|
len = Get14443bAnswerFromTag(rxdata, rxmaxlen, ISO14443B_READER_TIMEOUT, &eof_time);
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
|
|
||||||
data_bytes = response;
|
data_bytes = rxdata;
|
||||||
// restore timeout
|
// restore timeout
|
||||||
iso14b_set_timeout(save_iso14b_timeout);
|
iso14b_set_timeout(save_iso14b_timeout);
|
||||||
}
|
}
|
||||||
|
@ -1237,8 +1236,8 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we received I-block with chaining we need to send ACK and receive another block of data
|
// if we received I-block with chaining we need to send ACK and receive another block of data
|
||||||
if (response)
|
if (res)
|
||||||
*response = data_bytes[0];
|
*res = data_bytes[0];
|
||||||
|
|
||||||
// crc check
|
// crc check
|
||||||
if (len >= 3 && !check_crc(CRC_14443_B, data_bytes, len)) {
|
if (len >= 3 && !check_crc(CRC_14443_B, data_bytes, len)) {
|
||||||
|
@ -1524,7 +1523,7 @@ void iso14443b_setup(void) {
|
||||||
|
|
||||||
// Signal field is on with the appropriate LED
|
// Signal field is on with the appropriate LED
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD);
|
||||||
SpinDelay(100);
|
SpinDelay(50);
|
||||||
|
|
||||||
// Start the timer
|
// Start the timer
|
||||||
StartCountSspClk();
|
StartCountSspClk();
|
||||||
|
@ -1841,17 +1840,21 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
||||||
|
|
||||||
if ((param & ISO14B_CONNECT) == ISO14B_CONNECT) {
|
if ((param & ISO14B_CONNECT) == ISO14B_CONNECT) {
|
||||||
iso14443b_setup();
|
iso14443b_setup();
|
||||||
clear_trace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((param & ISO14B_SET_TIMEOUT))
|
if ((param & ISO14B_SET_TIMEOUT) == ISO14B_SET_TIMEOUT) {
|
||||||
iso14b_set_timeout(timeout);
|
iso14b_set_timeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((param & ISO14B_CLEARTRACE) == ISO14B_CLEARTRACE) {
|
||||||
|
clear_trace();
|
||||||
|
}
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
uint32_t sendlen = sizeof(iso14b_card_select_t);
|
uint32_t sendlen = sizeof(iso14b_card_select_t);
|
||||||
iso14b_card_select_t card;
|
iso14b_card_select_t card;
|
||||||
|
memset((void*)&card, 0x00, sizeof(card));
|
||||||
|
|
||||||
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
|
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
|
||||||
status = iso14443b_select_card(&card);
|
status = iso14443b_select_card(&card);
|
||||||
|
@ -1877,9 +1880,10 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((param & ISO14B_APDU) == ISO14B_APDU) {
|
if ((param & ISO14B_APDU) == ISO14B_APDU) {
|
||||||
status = iso14443b_apdu(cmd, len, (param & ISO14B_SEND_CHAINING), buf, sizeof(buf));
|
uint8_t res;
|
||||||
|
status = iso14443b_apdu(cmd, len, (param & ISO14B_SEND_CHAINING), buf, sizeof(buf), &res);
|
||||||
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
|
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
|
||||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, status, 0, buf, sendlen);
|
reply_mix(CMD_HF_ISO14443B_COMMAND, status, res, 0, buf, sendlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((param & ISO14B_RAW) == ISO14B_RAW) {
|
if ((param & ISO14B_RAW) == ISO14B_RAW) {
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void iso14443b_setup(void);
|
void iso14443b_setup(void);
|
||||||
int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, uint8_t *response, uint16_t respmaxlen);
|
int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *res);
|
||||||
|
|
||||||
int iso14443b_select_card(iso14b_card_select_t *card);
|
int iso14443b_select_card(iso14b_card_select_t *card);
|
||||||
int iso14443b_select_card_srx(iso14b_card_select_t *card);
|
int iso14443b_select_card_srx(iso14b_card_select_t *card);
|
||||||
|
|
|
@ -1479,6 +1479,7 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t
|
||||||
if (recv != NULL) {
|
if (recv != NULL) {
|
||||||
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
||||||
}
|
}
|
||||||
|
FpgaDisableTracing();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1494,6 +1495,7 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui
|
||||||
if (recv != NULL) {
|
if (recv != NULL) {
|
||||||
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
||||||
}
|
}
|
||||||
|
FpgaDisableTracing();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env -S pm3 -s
|
#!/usr/bin/env -S pm3 -s
|
||||||
|
|
||||||
mem load f mfc_default_keys m
|
mem load -f mfc_default_keys --mfc
|
||||||
mem load f t55xx_default_pwds t
|
mem load -f t55xx_default_pwds --t55xx
|
||||||
mem load f iclass_default_keys i
|
mem load -f iclass_default_keys --iclass
|
||||||
lf t55xx deviceconfig z p
|
lf t55xx deviceconfig z p
|
||||||
|
|
|
@ -14,7 +14,7 @@ lf search
|
||||||
|
|
||||||
rem Test of keri clone & read
|
rem Test of keri clone & read
|
||||||
lf t55xx wipe
|
lf t55xx wipe
|
||||||
lf keri clone 1337
|
lf keri clone --id 1337
|
||||||
lf keri read
|
lf keri read
|
||||||
lf search
|
lf search
|
||||||
|
|
||||||
|
|
|
@ -1927,10 +1927,8 @@ struct arg_file *arg_filen(
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "argtable3.h"
|
#include "argtable3.h"
|
||||||
|
|
||||||
|
|
||||||
static void arg_int_resetfn(struct arg_int *parent) {
|
static void arg_int_resetfn(struct arg_int *parent) {
|
||||||
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
|
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
|
||||||
parent->count = 0;
|
parent->count = 0;
|
||||||
|
@ -2226,6 +2224,263 @@ struct arg_int *arg_intn(
|
||||||
ARG_TRACE(("arg_intn() returns %p\n", result));
|
ARG_TRACE(("arg_intn() returns %p\n", result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// uint64_t support
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
static uint64_t strtollu0X(const char *str,
|
||||||
|
const char * *endptr,
|
||||||
|
char X,
|
||||||
|
int base) {
|
||||||
|
uint64_t val; /* stores result */
|
||||||
|
int s = 1; /* sign is +1 or -1 */
|
||||||
|
const char *ptr = str; /* ptr to current position in str */
|
||||||
|
|
||||||
|
/* skip leading whitespace */
|
||||||
|
while (ISSPACE(*ptr))
|
||||||
|
ptr++;
|
||||||
|
// printf("1) %s\n",ptr);
|
||||||
|
|
||||||
|
/* scan optional sign character */
|
||||||
|
switch (*ptr) {
|
||||||
|
case '+':
|
||||||
|
ptr++;
|
||||||
|
s = 1;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
ptr++;
|
||||||
|
s = -1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
s = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// printf("2) %s\n",ptr);
|
||||||
|
|
||||||
|
/* '0X' prefix */
|
||||||
|
if ((*ptr++) != '0') {
|
||||||
|
/* printf("failed to detect '0'\n"); */
|
||||||
|
*endptr = str;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// printf("3) %s\n",ptr);
|
||||||
|
if (toupper(*ptr++) != toupper(X)) {
|
||||||
|
/* printf("failed to detect '%c'\n",X); */
|
||||||
|
*endptr = str;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// printf("4) %s\n",ptr);
|
||||||
|
|
||||||
|
/* attempt conversion on remainder of string using strtol() */
|
||||||
|
val = strtoull(ptr, (char * *)endptr, base);
|
||||||
|
|
||||||
|
if (*endptr == ptr) {
|
||||||
|
/* conversion failed */
|
||||||
|
*endptr = str;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return s * val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void arg_u64_resetfn(struct arg_u64 *parent) {
|
||||||
|
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
|
||||||
|
parent->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arg_u64_scanfn(struct arg_u64 *parent, const char *argval) {
|
||||||
|
int errorcode = 0;
|
||||||
|
if (parent->count == parent->hdr.maxcount) {
|
||||||
|
/* maximum number of arguments exceeded */
|
||||||
|
errorcode = EMAXCOUNT;
|
||||||
|
} else if (!argval) {
|
||||||
|
/* a valid argument with no argument value was given. */
|
||||||
|
/* This happens when an optional argument value was invoked. */
|
||||||
|
/* leave parent arguiment value unaltered but still count the argument. */
|
||||||
|
parent->count++;
|
||||||
|
} else {
|
||||||
|
uint64_t val;
|
||||||
|
const char *end;
|
||||||
|
|
||||||
|
/* attempt to extract hex integer (eg: +0x123) from argval into val conversion */
|
||||||
|
val = strtollu0X(argval, &end, 'X', 16);
|
||||||
|
if (end == argval) {
|
||||||
|
/* hex failed, attempt octal conversion (eg +0o123) */
|
||||||
|
val = strtollu0X(argval, &end, 'O', 8);
|
||||||
|
if (end == argval) {
|
||||||
|
/* octal failed, attempt binary conversion (eg +0B101) */
|
||||||
|
val = strtollu0X(argval, &end, 'B', 2);
|
||||||
|
if (end == argval) {
|
||||||
|
/* binary failed, attempt decimal conversion with no prefix (eg 1234) */
|
||||||
|
val = strtoull(argval, (char * *)&end, 10);
|
||||||
|
if (end == argval) {
|
||||||
|
/* all supported number formats failed */
|
||||||
|
return EBADINT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Safety check for integer overflow. WARNING: this check */
|
||||||
|
/* achieves nothing on machines where size(int)==size(long). */
|
||||||
|
if (val > ULLONG_MAX)
|
||||||
|
#ifdef __STDC_WANT_SECURE_LIB__
|
||||||
|
errorcode = EOVERFLOW_;
|
||||||
|
#else
|
||||||
|
errorcode = EOVERFLOW;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Detect any suffixes (KB,MB,GB) and multiply argument value appropriately. */
|
||||||
|
/* We need to be mindful of integer overflows when using such big numbers. */
|
||||||
|
if (detectsuffix(end, "KB")) { /* kilobytes */
|
||||||
|
if (val > (ULLONG_MAX / 1024))
|
||||||
|
#ifdef __STDC_WANT_SECURE_LIB__
|
||||||
|
errorcode = EOVERFLOW_; /* Overflow would occur if we proceed */
|
||||||
|
#else
|
||||||
|
errorcode = EOVERFLOW; /* Overflow would occur if we proceed */
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
val *= 1024; /* 1KB = 1024 */
|
||||||
|
} else if (detectsuffix(end, "MB")) { /* megabytes */
|
||||||
|
if (val > (ULLONG_MAX / 1048576))
|
||||||
|
#ifdef __STDC_WANT_SECURE_LIB__
|
||||||
|
errorcode = EOVERFLOW_; /* Overflow would occur if we proceed */
|
||||||
|
#else
|
||||||
|
errorcode = EOVERFLOW; /* Overflow would occur if we proceed */
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
val *= 1048576; /* 1MB = 1024*1024 */
|
||||||
|
} else if (detectsuffix(end, "GB")) { /* gigabytes */
|
||||||
|
if (val > (ULLONG_MAX / 1073741824))
|
||||||
|
#ifdef __STDC_WANT_SECURE_LIB__
|
||||||
|
errorcode = EOVERFLOW_; /* Overflow would occur if we proceed */
|
||||||
|
#else
|
||||||
|
errorcode = EOVERFLOW; /* Overflow would occur if we proceed */
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
val *= 1073741824; /* 1GB = 1024*1024*1024 */
|
||||||
|
} else if (!detectsuffix(end, ""))
|
||||||
|
errorcode = EBADINT; /* invalid suffix detected */
|
||||||
|
|
||||||
|
/* if success then store result in parent->uval[] array */
|
||||||
|
if (errorcode == 0)
|
||||||
|
parent->uval[parent->count++] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* printf("%s:scanfn(%p,%p) returns %d\n",__FILE__,parent,argval,errorcode); */
|
||||||
|
return errorcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arg_u64_checkfn(struct arg_u64 *parent) {
|
||||||
|
int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
|
||||||
|
/*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/
|
||||||
|
return errorcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void arg_u64_errorfn(
|
||||||
|
struct arg_u64 *parent,
|
||||||
|
FILE *fp,
|
||||||
|
int errorcode,
|
||||||
|
const char *argval,
|
||||||
|
const char *progname) {
|
||||||
|
const char *shortopts = parent->hdr.shortopts;
|
||||||
|
const char *longopts = parent->hdr.longopts;
|
||||||
|
const char *datatype = parent->hdr.datatype;
|
||||||
|
|
||||||
|
/* make argval NULL safe */
|
||||||
|
argval = argval ? argval : "";
|
||||||
|
|
||||||
|
fprintf(fp, "%s: ", progname);
|
||||||
|
switch (errorcode) {
|
||||||
|
case EMINCOUNT:
|
||||||
|
fputs("missing option ", fp);
|
||||||
|
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EMAXCOUNT:
|
||||||
|
fputs("excess option ", fp);
|
||||||
|
arg_print_option(fp, shortopts, longopts, argval, "\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EBADINT:
|
||||||
|
fprintf(fp, "invalid argument \"%s\" to option ", argval);
|
||||||
|
arg_print_option(fp, shortopts, longopts, datatype, "\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef __STDC_WANT_SECURE_LIB__
|
||||||
|
case EOVERFLOW_:
|
||||||
|
#else
|
||||||
|
case EOVERFLOW:
|
||||||
|
#endif
|
||||||
|
fputs("integer overflow at option ", fp);
|
||||||
|
arg_print_option(fp, shortopts, longopts, datatype, " ");
|
||||||
|
fprintf(fp, "(%s is too large)\n", argval);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct arg_u64 *arg_u64_0(
|
||||||
|
const char *shortopts,
|
||||||
|
const char *longopts,
|
||||||
|
const char *datatype,
|
||||||
|
const char *glossary) {
|
||||||
|
return arg_u64_n(shortopts, longopts, datatype, 0, 1, glossary);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct arg_u64 *arg_u64_1(
|
||||||
|
const char *shortopts,
|
||||||
|
const char *longopts,
|
||||||
|
const char *datatype,
|
||||||
|
const char *glossary) {
|
||||||
|
return arg_u64_n(shortopts, longopts, datatype, 1, 1, glossary);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct arg_u64 *arg_u64_n(
|
||||||
|
const char *shortopts,
|
||||||
|
const char *longopts,
|
||||||
|
const char *datatype,
|
||||||
|
int mincount,
|
||||||
|
int maxcount,
|
||||||
|
const char *glossary) {
|
||||||
|
size_t nbytes;
|
||||||
|
struct arg_u64 *result;
|
||||||
|
|
||||||
|
/* foolproof things by ensuring maxcount is not less than mincount */
|
||||||
|
maxcount = (maxcount < mincount) ? mincount : maxcount;
|
||||||
|
|
||||||
|
nbytes = sizeof(struct arg_u64) /* storage for struct arg_u64 */
|
||||||
|
+ maxcount * sizeof(uint64_t); /* storage for uval[maxcount] array */
|
||||||
|
|
||||||
|
result = (struct arg_u64 *)malloc(nbytes);
|
||||||
|
if (result) {
|
||||||
|
/* init the arg_hdr struct */
|
||||||
|
result->hdr.flag = ARG_HASVALUE;
|
||||||
|
result->hdr.shortopts = shortopts;
|
||||||
|
result->hdr.longopts = longopts;
|
||||||
|
result->hdr.datatype = datatype ? datatype : "<u64>";
|
||||||
|
result->hdr.glossary = glossary;
|
||||||
|
result->hdr.mincount = mincount;
|
||||||
|
result->hdr.maxcount = maxcount;
|
||||||
|
result->hdr.parent = result;
|
||||||
|
result->hdr.resetfn = (arg_resetfn *)arg_u64_resetfn;
|
||||||
|
result->hdr.scanfn = (arg_scanfn *)arg_u64_scanfn;
|
||||||
|
result->hdr.checkfn = (arg_checkfn *)arg_u64_checkfn;
|
||||||
|
result->hdr.errorfn = (arg_errorfn *)arg_u64_errorfn;
|
||||||
|
|
||||||
|
/* store the uval[maxcount] array immediately after the arg_int struct */
|
||||||
|
result->uval = (uint64_t *)(result + 1);
|
||||||
|
result->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ARG_TRACE(("arg_u64_n() returns %p\n", result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* This file is part of the argtable3 library.
|
* This file is part of the argtable3 library.
|
||||||
*
|
*
|
||||||
|
@ -4020,7 +4275,10 @@ static void arg_parse_untagged(int argc,
|
||||||
/* register an error for each unused argv[] entry */
|
/* register an error for each unused argv[] entry */
|
||||||
while (optind < argc) {
|
while (optind < argc) {
|
||||||
/*printf("arg_parse_untagged(): argv[%d]=\"%s\" not consumed\n",optind,argv[optind]);*/
|
/*printf("arg_parse_untagged(): argv[%d]=\"%s\" not consumed\n",optind,argv[optind]);*/
|
||||||
arg_register_error(endtable, endtable, ARG_ENOMATCH, argv[optind++]);
|
if (argv[optind][0] != '\x00') {
|
||||||
|
arg_register_error(endtable, endtable, ARG_ENOMATCH, argv[optind]);
|
||||||
|
}
|
||||||
|
optind++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -4195,7 +4453,8 @@ static void arg_cat_option(char *dest,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (datatype) {
|
if (datatype) {
|
||||||
arg_cat(&dest, "=", &ndest);
|
// arg_cat(&dest, "=", &ndest);
|
||||||
|
arg_cat(&dest, " ", &ndest);
|
||||||
if (optvalue) {
|
if (optvalue) {
|
||||||
arg_cat(&dest, "[", &ndest);
|
arg_cat(&dest, "[", &ndest);
|
||||||
arg_cat(&dest, datatype, &ndest);
|
arg_cat(&dest, datatype, &ndest);
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include <stdio.h> /* FILE */
|
#include <stdio.h> /* FILE */
|
||||||
#include <time.h> /* struct tm */
|
#include <time.h> /* struct tm */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -110,6 +111,12 @@ struct arg_int {
|
||||||
int *ival; /* Array of parsed argument values */
|
int *ival; /* Array of parsed argument values */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct arg_u64 {
|
||||||
|
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||||
|
int count; /* Number of matching command line args */
|
||||||
|
uint64_t *uval; /* Array of parsed argument values */
|
||||||
|
};
|
||||||
|
|
||||||
struct arg_dbl {
|
struct arg_dbl {
|
||||||
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
struct arg_hdr hdr; /* The mandatory argtable header struct */
|
||||||
int count; /* Number of matching command line args */
|
int count; /* Number of matching command line args */
|
||||||
|
@ -176,32 +183,29 @@ struct arg_lit *arg_litn(const char *shortopts,
|
||||||
int maxcount,
|
int maxcount,
|
||||||
const char *glossary);
|
const char *glossary);
|
||||||
|
|
||||||
struct arg_key *arg_key0(const char *keyword,
|
struct arg_key *arg_key0(const char *keyword, int flags, const char *glossary);
|
||||||
int flags,
|
struct arg_key *arg_key1(const char *keyword, int flags, const char *glossary);
|
||||||
|
struct arg_key *arg_keyn(const char *keyword, int flags, int mincount, int maxcount, const char *glossary);
|
||||||
|
|
||||||
|
struct arg_int *arg_int0(const char *shortopts, const char *longopts, const char *datatype, const char *glossary);
|
||||||
|
struct arg_int *arg_int1(const char *shortopts, const char *longopts, const char *datatype, const char *glossary);
|
||||||
|
struct arg_int *arg_intn(const char *shortopts, const char *longopts, const char *datatype, int mincount, int maxcount, const char *glossary);
|
||||||
|
|
||||||
|
struct arg_u64 *arg_u64_0(const char *shortopts,
|
||||||
|
const char *longopts,
|
||||||
|
const char *datatype,
|
||||||
const char *glossary);
|
const char *glossary);
|
||||||
struct arg_key *arg_key1(const char *keyword,
|
struct arg_u64 *arg_u64_1(const char *shortopts,
|
||||||
int flags,
|
const char *longopts,
|
||||||
|
const char *datatype,
|
||||||
const char *glossary);
|
const char *glossary);
|
||||||
struct arg_key *arg_keyn(const char *keyword,
|
struct arg_u64 *arg_u64_n(const char *shortopts,
|
||||||
int flags,
|
const char *longopts,
|
||||||
|
const char *datatype,
|
||||||
int mincount,
|
int mincount,
|
||||||
int maxcount,
|
int maxcount,
|
||||||
const char *glossary);
|
const char *glossary);
|
||||||
|
|
||||||
struct arg_int *arg_int0(const char *shortopts,
|
|
||||||
const char *longopts,
|
|
||||||
const char *datatype,
|
|
||||||
const char *glossary);
|
|
||||||
struct arg_int *arg_int1(const char *shortopts,
|
|
||||||
const char *longopts,
|
|
||||||
const char *datatype,
|
|
||||||
const char *glossary);
|
|
||||||
struct arg_int *arg_intn(const char *shortopts,
|
|
||||||
const char *longopts,
|
|
||||||
const char *datatype,
|
|
||||||
int mincount,
|
|
||||||
int maxcount,
|
|
||||||
const char *glossary);
|
|
||||||
|
|
||||||
struct arg_dbl *arg_dbl0(const char *shortopts,
|
struct arg_dbl *arg_dbl0(const char *shortopts,
|
||||||
const char *longopts,
|
const char *longopts,
|
||||||
|
|
|
@ -251,12 +251,13 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
||||||
if (!ibuf)
|
if (!ibuf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (ibuf > maxdatalen) {
|
if (ibuf + 1 > maxdatalen) {
|
||||||
|
printf("Parameter error: string too long, expect max %i chars\n", maxdatalen - 1);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(data, tmp_buf, ibuf);
|
memcpy(data, tmp_buf, ibuf + 1);
|
||||||
*datalen = ibuf;
|
*datalen = ibuf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,22 +17,39 @@
|
||||||
#define arg_param_begin arg_lit0("h", "help", "This help")
|
#define arg_param_begin arg_lit0("h", "help", "This help")
|
||||||
#define arg_param_end arg_end(20)
|
#define arg_param_end arg_end(20)
|
||||||
|
|
||||||
#define arg_getsize(a) (sizeof(a) / sizeof(a[0]))
|
#define arg_getsize(a) (sizeof(a) / sizeof(a[0]))
|
||||||
#define arg_get_lit(ctx, n) (((struct arg_lit*)((ctx)->argtable)[n])->count)
|
#define arg_get_lit(ctx, n) (((struct arg_lit*)((ctx)->argtable)[(n)])->count)
|
||||||
#define arg_get_int_count(ctx, n)(((struct arg_int*)((ctx)->argtable)[n])->count)
|
|
||||||
#define arg_get_int(ctx, n) (((struct arg_int*)((ctx)->argtable)[n])->ival[0])
|
#define arg_get_int_count(ctx, n) (((struct arg_int*)((ctx)->argtable)[(n)])->count)
|
||||||
#define arg_get_int_def(ctx, n, def)(arg_get_int_count((ctx), n) ? (arg_get_int((ctx), n)) : (def))
|
#define arg_get_int(ctx, n) (((struct arg_int*)((ctx)->argtable)[(n)])->ival[0])
|
||||||
#define arg_get_str(ctx, n) ((struct arg_str*)((ctx)->argtable)[n])
|
#define arg_get_int_def(ctx, n, def)(arg_get_int_count((ctx), (n)) ? (arg_get_int((ctx), (n))) : (def))
|
||||||
#define arg_get_str_len(ctx, n) (strlen(((struct arg_str*)((ctx)->argtable)[n])->sval[0]))
|
|
||||||
|
#define arg_get_dbl_count(ctx, n) (((struct arg_dbl*)((ctx)->argtable)[(n)])->count)
|
||||||
|
#define arg_get_dbl(ctx, n) (((struct arg_dbl*)((ctx)->argtable)[(n)])->dval[0])
|
||||||
|
#define arg_get_dbl_def(ctx, n, def)(arg_get_dbl_count((ctx), (n)) ? (arg_get_dbl((ctx), (n))) : (def))
|
||||||
|
|
||||||
|
#define arg_get_u32(ctx, n) (uint32_t)(((struct arg_u64*)((ctx)->argtable)[(n)])->uval[0])
|
||||||
|
#define arg_get_u32_def(ctx, n, def) (arg_get_u64_count((ctx), (n)) ? (arg_get_u32((ctx), (n))) : (uint32_t)(def))
|
||||||
|
|
||||||
|
#define arg_get_u64_count(ctx, n) (((struct arg_u64*)((ctx)->argtable)[(n)])->count)
|
||||||
|
#define arg_get_u64(ctx, n) (((struct arg_u64*)((ctx)->argtable)[(n)])->uval[0])
|
||||||
|
#define arg_get_u64_def(ctx, n, def) (arg_get_u64_count((ctx), (n)) ? (arg_get_u64((ctx), (n))) : (uint64_t)(def))
|
||||||
|
|
||||||
|
#define arg_get_str(ctx, n) ((struct arg_str*)((ctx)->argtable)[(n)])
|
||||||
|
#define arg_get_str_len(ctx, n) (strlen(((struct arg_str*)((ctx)->argtable)[(n)])->sval[0]))
|
||||||
|
|
||||||
#define arg_strx1(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 1, 250, (glossary)))
|
#define arg_strx1(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 1, 250, (glossary)))
|
||||||
#define arg_strx0(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 0, 250, (glossary)))
|
#define arg_strx0(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 0, 250, (glossary)))
|
||||||
|
|
||||||
#define CLIParserFree(ctx) if ((ctx)) {arg_freetable(ctx->argtable, ctx->argtableLen); free((ctx)); (ctx)=NULL;}
|
#define CLIParserFree(ctx) if ((ctx)) {arg_freetable((ctx)->argtable, (ctx)->argtableLen); free((ctx)); (ctx)=NULL;}
|
||||||
#define CLIExecWithReturn(ctx, cmd, atbl, ifempty) if (CLIParserParseString(ctx, cmd, atbl, arg_getsize(atbl), ifempty)) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
|
||||||
#define CLIGetHexBLessWithReturn(ctx, paramnum, data, datalen, delta) if (CLIParamHexToBuf(arg_get_str(ctx, paramnum), data, sizeof(data) - (delta), datalen)) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
#define CLIExecWithReturn(ctx, cmd, atbl, ifempty) if (CLIParserParseString((ctx), (cmd), (atbl), arg_getsize((atbl)), (ifempty))) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
||||||
#define CLIGetHexWithReturn(ctx, paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str(ctx, paramnum), data, sizeof(data), datalen)) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
|
||||||
#define CLIGetStrWithReturn(ctx, paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str(ctx, paramnum), data, sizeof(data), datalen)) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
#define CLIGetHexBLessWithReturn(ctx, paramnum, data, datalen, delta) if (CLIParamHexToBuf(arg_get_str((ctx), (paramnum)), (data), sizeof((data)) - (delta), (datalen))) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
||||||
|
|
||||||
|
#define CLIGetHexWithReturn(ctx, paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str((ctx), (paramnum)), (data), sizeof((data)), (datalen))) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
||||||
|
|
||||||
|
#define CLIGetStrWithReturn(ctx, paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str((ctx), (paramnum)), (data), sizeof((data)), (datalen))) {CLIParserFree((ctx)); return PM3_ESOFT;}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void **argtable;
|
void **argtable;
|
||||||
|
|
|
@ -32,7 +32,7 @@ device-side.
|
||||||
local function calypso_parse(result)
|
local function calypso_parse(result)
|
||||||
local r = Command.parse(result)
|
local r = Command.parse(result)
|
||||||
if r.arg1 >= 0 then
|
if r.arg1 >= 0 then
|
||||||
local len = r.arg2 * 2
|
local len = r.arg1 * 2
|
||||||
if len > 0 then
|
if len > 0 then
|
||||||
r.data = string.sub(r.data, 0, len);
|
r.data = string.sub(r.data, 0, len);
|
||||||
return r, nil
|
return r, nil
|
||||||
|
@ -113,8 +113,9 @@ end
|
||||||
local function calypso_send_cmd_raw(data, ignoreresponse )
|
local function calypso_send_cmd_raw(data, ignoreresponse )
|
||||||
|
|
||||||
local command, flags, result, err
|
local command, flags, result, err
|
||||||
flags = lib14b.ISO14B_COMMAND.ISO14B_RAW +
|
flags = lib14b.ISO14B_COMMAND.ISO14B_APDU
|
||||||
lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC
|
-- flags = lib14b.ISO14B_COMMAND.ISO14B_RAW +
|
||||||
|
-- lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC
|
||||||
|
|
||||||
data = data or "00"
|
data = data or "00"
|
||||||
|
|
||||||
|
@ -162,6 +163,7 @@ local function calypso_apdu_status(apdu)
|
||||||
return status, desc, err
|
return status, desc, err
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local CLA = '94'
|
||||||
local _calypso_cmds = {
|
local _calypso_cmds = {
|
||||||
|
|
||||||
-- Break down of command bytes:
|
-- Break down of command bytes:
|
||||||
|
@ -184,27 +186,25 @@ local _calypso_cmds = {
|
||||||
-- Electronic Purse file
|
-- Electronic Purse file
|
||||||
-- Electronic Transaction log file
|
-- Electronic Transaction log file
|
||||||
|
|
||||||
|
['01.Select ICC file'] = CLA..'a4 080004 3f00 0002',
|
||||||
--['01.Select ICC file'] = '0294 a4 00 0002 3f00',
|
['02.ICC'] = CLA..'b2 01 041d',
|
||||||
['01.Select ICC file'] = '0294 a4 080004 3f00 0002',
|
['03.Select EnvHol file'] = CLA..'a4 080004 2000 2001',
|
||||||
['02.ICC'] = '0394 b2 01 041d',
|
['04.EnvHol1'] = CLA..'b2 01 041d',
|
||||||
['03.Select EnvHol file'] = '0294 a4 080004 2000 2001',
|
['05.Select EvLog file'] = CLA..'a4 080004 2000 2010',
|
||||||
['04.EnvHol1'] = '0394 b2 01 041d',
|
['06.EvLog1'] = CLA..'b2 01 041d',
|
||||||
['05.Select EvLog file'] = '0294 a4 080004 2000 2010',
|
['07.EvLog2'] = CLA..'b2 02 041d',
|
||||||
['06.EvLog1'] = '0394 b2 01 041d',
|
['08.EvLog3'] = CLA..'b2 03 041d',
|
||||||
['07.EvLog2'] = '0294 b2 02 041d',
|
['09.Select ConList file']= CLA..'a4 080004 2000 2050',
|
||||||
['08.EvLog3'] = '0394 b2 03 041d',
|
['10.ConList'] = CLA..'b2 01 041d',
|
||||||
['09.Select ConList file']= '0294 a4 080004 2000 2050',
|
['11.Select Contra file'] = CLA..'a4 080004 2000 2020',
|
||||||
['10.ConList'] = '0394 b2 01 041d',
|
['12.Contra1'] = CLA..'b2 01 041d',
|
||||||
['11.Select Contra file'] = '0294 a4 080004 2000 2020',
|
['13.Contra2'] = CLA..'b2 02 041d',
|
||||||
['12.Contra1'] = '0394 b2 01 041d',
|
['14.Contra3'] = CLA..'b2 03 041d',
|
||||||
['13.Contra2'] = '0294 b2 02 041d',
|
['15.Contra4'] = CLA..'b2 04 041d',
|
||||||
['14.Contra3'] = '0394 b2 03 041d',
|
['16.Select Counter file']= CLA..'a4 080004 2000 2069',
|
||||||
['15.Contra4'] = '0294 b2 04 041d',
|
['17.Counter'] = CLA..'b2 01 041d',
|
||||||
['16.Select Counter file']= '0394 a4 080004 2000 2069',
|
['18.Select SpecEv file'] = CLA..'a4 080004 2000 2040',
|
||||||
['17.Counter'] = '0294 b2 01 041d',
|
['19.SpecEv1'] = CLA..'b2 01 041d',
|
||||||
['18.Select SpecEv file'] = '0394 a4 080004 2000 2040',
|
|
||||||
['19.SpecEv1'] = '0294 b2 01 041d',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
277
client/luascripts/hf_14b_mobib.lua
Normal file
277
client/luascripts/hf_14b_mobib.lua
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
local cmds = require('commands')
|
||||||
|
local getopt = require('getopt')
|
||||||
|
local lib14b = require('read14b')
|
||||||
|
local utils = require('utils')
|
||||||
|
local iso7816 = require('7816_error')
|
||||||
|
local ansicolors = require('ansicolors')
|
||||||
|
|
||||||
|
copyright = ''
|
||||||
|
author = 'Iceman'
|
||||||
|
version = 'v1.0.0'
|
||||||
|
desc = [[
|
||||||
|
This is a script to communicate with a MOBIB tag using the '14b raw' commands
|
||||||
|
]]
|
||||||
|
example = [[
|
||||||
|
script run hf_14b_mobib
|
||||||
|
script run hf_14b_mobib -b 11223344
|
||||||
|
|
||||||
|
]]
|
||||||
|
usage = [[
|
||||||
|
script run hf_14b_mobib -h -b
|
||||||
|
]]
|
||||||
|
arguments = [[
|
||||||
|
h this helptext
|
||||||
|
b raw bytes to send
|
||||||
|
]]
|
||||||
|
|
||||||
|
--[[
|
||||||
|
This script communicates with /armsrc/iso14443b.c,
|
||||||
|
Check there for details about data format and how commands are interpreted on the
|
||||||
|
device-side.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function calypso_parse(result)
|
||||||
|
local r = Command.parse(result)
|
||||||
|
if r.arg1 >= 0 then
|
||||||
|
local len = r.arg1 * 2
|
||||||
|
if len > 0 then
|
||||||
|
r.data = string.sub(r.data, 0, len);
|
||||||
|
return r, nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil,nil
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- A debug printout-function
|
||||||
|
local function dbg(args)
|
||||||
|
if not DEBUG then return end
|
||||||
|
if type(args) == 'table' then
|
||||||
|
local i = 1
|
||||||
|
while args[i] do
|
||||||
|
dbg(args[i])
|
||||||
|
i = i+1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print('###', args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- This is only meant to be used when errors occur
|
||||||
|
local function oops(err)
|
||||||
|
print('ERROR: ', err)
|
||||||
|
lib14b.disconnect()
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- Usage help
|
||||||
|
local function help()
|
||||||
|
print(copyright)
|
||||||
|
print(author)
|
||||||
|
print(version)
|
||||||
|
print(desc)
|
||||||
|
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||||
|
print(usage)
|
||||||
|
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||||
|
print(arguments)
|
||||||
|
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||||
|
print(example)
|
||||||
|
end
|
||||||
|
--
|
||||||
|
-- helper function, give current count of items in lua-table.
|
||||||
|
local function tablelen(T)
|
||||||
|
local count = 0
|
||||||
|
for _ in pairs(T) do count = count + 1 end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- helper function, gives a sorted table from table t,
|
||||||
|
-- order can be a seperate sorting-order function.
|
||||||
|
local function spairs(t, order)
|
||||||
|
-- collect the keys
|
||||||
|
local keys = {}
|
||||||
|
for k in pairs(t) do keys[#keys+1] = k end
|
||||||
|
|
||||||
|
-- if order function given, sort by it by passing the table and keys a, b,
|
||||||
|
-- otherwise just sort the keys
|
||||||
|
if order then
|
||||||
|
table.sort(keys, function(a,b) return order(t, a, b) end)
|
||||||
|
else
|
||||||
|
table.sort(keys)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- return the iterator function
|
||||||
|
local i = 0
|
||||||
|
return function()
|
||||||
|
i = i + 1
|
||||||
|
if keys[i] then
|
||||||
|
return keys[i], t[keys[i]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- Sends a usbpackage , "hf 14b raw"
|
||||||
|
-- if it reads the response, it converts it to a lua object "Command" first and the Data is cut to correct length.
|
||||||
|
local function calypso_send_cmd_raw(data, ignoreresponse )
|
||||||
|
|
||||||
|
local command, flags, result, err
|
||||||
|
flags = lib14b.ISO14B_COMMAND.ISO14B_APDU
|
||||||
|
|
||||||
|
data = data or "00"
|
||||||
|
|
||||||
|
command = Command:newMIX{
|
||||||
|
cmd = cmds.CMD_HF_ISO14443B_COMMAND,
|
||||||
|
arg1 = flags,
|
||||||
|
arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string
|
||||||
|
data = data} -- data bytes (commands etc)
|
||||||
|
|
||||||
|
local use_cmd_ack = true
|
||||||
|
result, err = command:sendMIX(ignoreresponse, 2000, use_cmd_ack)
|
||||||
|
if result then
|
||||||
|
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL', result)
|
||||||
|
if arg0 >= 0 then
|
||||||
|
return calypso_parse(result)
|
||||||
|
else
|
||||||
|
err = 'card response failed'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
err = 'No response from card'
|
||||||
|
end
|
||||||
|
return result, err
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- calypso_card_num : Reads card number from ATR and
|
||||||
|
-- writes it in the tree in decimal format.
|
||||||
|
local function calypso_card_num(card)
|
||||||
|
if not card then return end
|
||||||
|
local card_num = tonumber( card.uid:sub(1,8),16 )
|
||||||
|
print('')
|
||||||
|
print('Card UID ' ..ansicolors.green..card.uid:format('%x')..ansicolors.reset)
|
||||||
|
print('Card Number ' ..ansicolors.green..string.format('%u', card_num)..ansicolors.reset)
|
||||||
|
print('-----------------------')
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- analyse CALYPSO apdu status bytes.
|
||||||
|
local function calypso_apdu_status(apdu)
|
||||||
|
-- last two is CRC
|
||||||
|
-- next two is APDU status bytes.
|
||||||
|
local mess = 'FAIL'
|
||||||
|
local sw = apdu:sub( #apdu-7, #apdu-4)
|
||||||
|
desc, err = iso7816.tostring(sw)
|
||||||
|
--print ('SW', sw, desc, err )
|
||||||
|
local status = ( sw == '9000' )
|
||||||
|
return status, desc, err
|
||||||
|
end
|
||||||
|
|
||||||
|
local CLA = '00'
|
||||||
|
local _calypso_cmds = {
|
||||||
|
['01.SELECT AID 1TIC.ICA'] = CLA..'a4 0400 08 315449432e494341',
|
||||||
|
['02.Select ICC file a'] = CLA..'a4 0000 02 3f00',
|
||||||
|
['03.Select ICC file b'] = CLA..'a4 0000 02 0002',
|
||||||
|
['04.ICC'] = CLA..'b2 0104 1d',
|
||||||
|
['05.Select Holder file'] = CLA..'a4 0000 02 3f1c',
|
||||||
|
['06.Holder1'] = CLA..'b2 0104 1d',
|
||||||
|
['07.Holder2'] = CLA..'b2 0204 1d',
|
||||||
|
['08.Select EnvHol file a'] = CLA..'a4 0000 00',
|
||||||
|
['09.Select EnvHol file b'] = CLA..'a4 0000 02 2000',
|
||||||
|
['10.Select EnvHol file c'] = CLA..'a4 0000 02 2001',
|
||||||
|
['11.EnvHol1'] = CLA..'b2 0104 1d',
|
||||||
|
['11.EnvHol2'] = CLA..'b2 0204 1d',
|
||||||
|
['12.Select EvLog file'] = CLA..'a4 0000 02 2010',
|
||||||
|
['13.EvLog1'] = CLA..'b2 0104 1d',
|
||||||
|
['14.EvLog2'] = CLA..'b2 0204 1d',
|
||||||
|
['15.EvLog3'] = CLA..'b2 0304 1d',
|
||||||
|
['16.Select ConList file'] = CLA..'a4 0000 02 2050',
|
||||||
|
['17.ConList'] = CLA..'b2 0104 1d',
|
||||||
|
['18.Select Contra file'] = CLA..'a4 0000 02 2020',
|
||||||
|
['19.Contra1'] = CLA..'b2 0104 1d',
|
||||||
|
['20.Contra2'] = CLA..'b2 0204 1d',
|
||||||
|
['21.Contra3'] = CLA..'b2 0304 1d',
|
||||||
|
['22.Contra4'] = CLA..'b2 0404 1d',
|
||||||
|
['23.Contra5'] = CLA..'b2 0504 1d',
|
||||||
|
['24.Contra6'] = CLA..'b2 0604 1d',
|
||||||
|
['25.Contra7'] = CLA..'b2 0704 1d',
|
||||||
|
['26.Contra8'] = CLA..'b2 0804 1d',
|
||||||
|
['27.Contra9'] = CLA..'b2 0904 1d',
|
||||||
|
['28.ContraA'] = CLA..'b2 0a04 1d',
|
||||||
|
['29.ContraB'] = CLA..'b2 0b04 1d',
|
||||||
|
['30.ContraC'] = CLA..'b2 0c04 1d',
|
||||||
|
['31.Select Counter file'] = CLA..'a4 0000 02 2069',
|
||||||
|
['32.Counter'] = CLA..'b2 0104 1d',
|
||||||
|
['33.Select LoadLog file a'] = CLA..'a4 0000 00',
|
||||||
|
['34.Select LoadLog file b'] = CLA..'a4 0000 02 1000',
|
||||||
|
['35.Select LoadLog file c'] = CLA..'a4 0000 02 1014',
|
||||||
|
['36.LoadLog'] = CLA..'b2 0104 1d',
|
||||||
|
['37.Select Purcha file'] = CLA..'a4 0000 02 1015',
|
||||||
|
['38.Purcha1'] = CLA..'b2 0104 1d',
|
||||||
|
['39.Purcha2'] = CLA..'b2 0204 1d',
|
||||||
|
['40.Purcha3'] = CLA..'b2 0304 1d',
|
||||||
|
['41.Select SpecEv file a'] = CLA..'a4 0000 00',
|
||||||
|
['42.Select SpecEv file b'] = CLA..'a4 0000 02 2000',
|
||||||
|
['43.Select SpecEv file c'] = CLA..'a4 0000 02 2040',
|
||||||
|
['44.SpecEv1'] = CLA..'b2 0104 1d',
|
||||||
|
['45.SpecEv2'] = CLA..'b2 0204 1d',
|
||||||
|
['46.SpecEv3'] = CLA..'b2 0304 1d',
|
||||||
|
['47.SpecEv4'] = CLA..'b2 0404 1d',
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
-- The main entry point
|
||||||
|
function main(args)
|
||||||
|
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print( string.rep('--',20) )
|
||||||
|
print()
|
||||||
|
|
||||||
|
local data, apdu, flags, uid, cid, result, err, card
|
||||||
|
-- Read the parameters
|
||||||
|
for o, a in getopt.getopt(args, 'h') do
|
||||||
|
if o == 'h' then return help() end
|
||||||
|
if o == 'b' then bytes = a end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- lib14b.connect()
|
||||||
|
|
||||||
|
-- Select 14b tag.
|
||||||
|
card, err = lib14b.waitFor14443b()
|
||||||
|
if not card then return oops(err) end
|
||||||
|
|
||||||
|
calypso_card_num(card)
|
||||||
|
cid = card.cid
|
||||||
|
|
||||||
|
for i, apdu in spairs(_calypso_cmds) do
|
||||||
|
print('>> '..ansicolors.yellow..i..ansicolors.reset)
|
||||||
|
apdu = apdu:gsub('%s+', '')
|
||||||
|
result, err = calypso_send_cmd_raw(apdu , false)
|
||||||
|
if err then
|
||||||
|
print('<< '..err)
|
||||||
|
else
|
||||||
|
if result then
|
||||||
|
local status, desc, err = calypso_apdu_status(result.data)
|
||||||
|
local d = result.data:sub(3, (#result.data - 8))
|
||||||
|
if status then
|
||||||
|
print('<< '..d..' ('..ansicolors.green..'ok'..ansicolors.reset..')')
|
||||||
|
else
|
||||||
|
print('<< '..d..' '..ansicolors.red..err..ansicolors.reset )
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print('<< no answer')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lib14b.disconnect()
|
||||||
|
end
|
||||||
|
---
|
||||||
|
-- a simple selftest function, tries to convert
|
||||||
|
function selftest()
|
||||||
|
DEBUG = true
|
||||||
|
dbg('Performing test')
|
||||||
|
dbg('Tests done')
|
||||||
|
end
|
||||||
|
-- Flip the switch here to perform a sanity check.
|
||||||
|
-- It read a nonce in two different ways, as specified in the usage-section
|
||||||
|
if '--test'==args then
|
||||||
|
selftest()
|
||||||
|
else
|
||||||
|
-- Call the main
|
||||||
|
main(args)
|
||||||
|
end
|
|
@ -74,9 +74,9 @@ function main(args)
|
||||||
-- Upload dictionaries
|
-- Upload dictionaries
|
||||||
print('Uploading dictionaries to RDV4 flashmemory')
|
print('Uploading dictionaries to RDV4 flashmemory')
|
||||||
print(dash)
|
print(dash)
|
||||||
core.console('mem load f mfc_default_keys m')
|
core.console('mem load -f mfc_default_keys --mfc')
|
||||||
core.console('mem load f t55xx_default_pwds t')
|
core.console('mem load -f t55xx_default_pwds --t55xx')
|
||||||
core.console('mem load f iclass_default_keys i')
|
core.console('mem load -f iclass_default_keys --iclass')
|
||||||
print(dash)
|
print(dash)
|
||||||
|
|
||||||
-- T55x7 Device configuration
|
-- T55x7 Device configuration
|
||||||
|
|
|
@ -50,20 +50,6 @@ static int usage_data_save(void) {
|
||||||
PrintAndLogEx(NORMAL, " data save f mytrace w - save graphbuffer to wave file");
|
PrintAndLogEx(NORMAL, " data save f mytrace w - save graphbuffer to wave file");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
static int usage_data_scale(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Set cursor display scale.");
|
|
||||||
PrintAndLogEx(NORMAL, "Setting the scale makes the differential `dt` reading between the yellow and purple markers meaningful. ");
|
|
||||||
PrintAndLogEx(NORMAL, "once the scale is set, the differential reading between brackets is the time duration in seconds.");
|
|
||||||
PrintAndLogEx(NORMAL, "For example, if acquiring in 125kHz, use scale 125.");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: data scale [h] <kHz>");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h this help");
|
|
||||||
PrintAndLogEx(NORMAL, " <kHz> sets scale of carrier frequency expressed in kHz");
|
|
||||||
PrintAndLogEx(NORMAL, "Samples:");
|
|
||||||
PrintAndLogEx(NORMAL, " data scale 125 - if sampled in 125kHz");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_data_printdemodbuf(void) {
|
static int usage_data_printdemodbuf(void) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o <offset> l <length>");
|
PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o <offset> l <length>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
|
@ -1825,7 +1811,8 @@ static int CmdMtrim(const char *Cmd) {
|
||||||
uint32_t start = 0, stop = 0;
|
uint32_t start = 0, stop = 0;
|
||||||
sscanf(Cmd, "%u %u", &start, &stop);
|
sscanf(Cmd, "%u %u", &start, &stop);
|
||||||
|
|
||||||
if (start > GraphTraceLen || stop > GraphTraceLen || start > stop) return PM3_ESOFT;
|
if (start > GraphTraceLen || stop > GraphTraceLen || start >= stop)
|
||||||
|
return PM3_ESOFT;
|
||||||
|
|
||||||
// leave start position sample
|
// leave start position sample
|
||||||
start++;
|
start++;
|
||||||
|
@ -1912,14 +1899,32 @@ int CmdSave(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdScale(const char *Cmd) {
|
static int CmdScale(const char *Cmd) {
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
|
||||||
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_data_scale();
|
|
||||||
|
|
||||||
CursorScaleFactor = atoi(Cmd);
|
CLIParserContext *ctx;
|
||||||
if (CursorScaleFactor == 0) {
|
CLIParserInit(&ctx, "data scale",
|
||||||
PrintAndLogEx(FAILED, "bad, can't have zero scale");
|
"Set cursor display scale.\n"
|
||||||
|
"Setting the scale makes the differential `dt` reading between the yellow and purple markers meaningful.\n"
|
||||||
|
"once the scale is set, the differential reading between brackets can become a time duration.",
|
||||||
|
"data scale --sr 125 -u ms -> for LF sampled at 125 kHz. Reading will be in milliseconds\n"
|
||||||
|
"data scale --sr 1.695 -u us -> for HF sampled at 1.695 MHz. Reading will be in microseconds\n"
|
||||||
|
"data scale --sr 16 -u ETU -> for HF with 16 samples per ETU. Reading will be in ETUs"
|
||||||
|
);
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_dbl1(NULL, "sr", "<float>", "sets scale according to sampling rate"),
|
||||||
|
arg_str0("u", "unit", "<string>", "time unit to display (max 10 chars)"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
CursorScaleFactor = arg_get_dbl_def(ctx, 1, 1);
|
||||||
|
if (CursorScaleFactor <= 0) {
|
||||||
|
PrintAndLogEx(FAILED, "bad, can't have negative or zero scale");
|
||||||
CursorScaleFactor = 1;
|
CursorScaleFactor = 1;
|
||||||
}
|
}
|
||||||
|
int len = 0;
|
||||||
|
CursorScaleFactorUnit[0] = '\x00';
|
||||||
|
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t*)CursorScaleFactorUnit, sizeof(CursorScaleFactorUnit), &len);
|
||||||
|
CLIParserFree(ctx);
|
||||||
RepaintGraphWindow();
|
RepaintGraphWindow();
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,13 @@
|
||||||
// Proxmark3 RDV40 Flash memory commands
|
// Proxmark3 RDV40 Flash memory commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "cmdflashmem.h"
|
#include "cmdflashmem.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include "cmdparser.h" // command_t
|
||||||
#include "cmdparser.h" // command_t
|
#include "cliparser.h"
|
||||||
|
|
||||||
#include "pmflash.h"
|
#include "pmflash.h"
|
||||||
#include "fileutils.h" //saveFile
|
#include "fileutils.h" // saveFile
|
||||||
#include "comms.h" //getfromdevice
|
#include "comms.h" // getfromdevice
|
||||||
#include "cmdflashmemspiffs.h" // spiffs commands
|
#include "cmdflashmemspiffs.h" // spiffs commands
|
||||||
|
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
|
|
||||||
|
@ -29,90 +26,34 @@
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_flashmem_spibaud(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] <baudrate>");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h this help");
|
|
||||||
PrintAndLogEx(NORMAL, " <baudrate> SPI baudrate in MHz [24|48]");
|
|
||||||
PrintAndLogEx(NORMAL, " ");
|
|
||||||
PrintAndLogEx(NORMAL, " If >= 24MHz, FASTREADS instead of READS instruction will be used.");
|
|
||||||
PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48MHz setting");
|
|
||||||
PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24MHz");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, " mem spibaud 48");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int usage_flashmem_load(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: mem load [o <offset>] f <file name> [m|t|i]");
|
|
||||||
PrintAndLogEx(NORMAL, "Warning: mem area to be written must have been wiped first");
|
|
||||||
PrintAndLogEx(NORMAL, "(this is already taken care when loading dictionaries)");
|
|
||||||
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
|
|
||||||
PrintAndLogEx(NORMAL, " f <filename> : file name");
|
|
||||||
PrintAndLogEx(NORMAL, " m : upload 6 bytes keys (mifare key dictionary)");
|
|
||||||
PrintAndLogEx(NORMAL, " i : upload 8 bytes keys (iClass key dictionary)");
|
|
||||||
PrintAndLogEx(NORMAL, " t : upload 4 bytes keys (pwd dictionary)");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0
|
|
||||||
PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024
|
|
||||||
PrintAndLogEx(NORMAL, " mem load f mfc_default_keys m");
|
|
||||||
PrintAndLogEx(NORMAL, " mem load f t55xx_default_pwds t");
|
|
||||||
PrintAndLogEx(NORMAL, " mem load f iclass_default_keys i");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_flashmem_dump(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Dumps flash memory on device into a file or in console");
|
|
||||||
PrintAndLogEx(NORMAL, " Usage: mem dump [o <offset>] [l <length>] [f <file name>] [p]");
|
|
||||||
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
|
|
||||||
PrintAndLogEx(NORMAL, " l <length> : length");
|
|
||||||
PrintAndLogEx(NORMAL, " f <filename> : file name");
|
|
||||||
PrintAndLogEx(NORMAL, " p : print dump in console");
|
|
||||||
PrintAndLogEx(NORMAL, " You must specify at lease option f or option p, both if you wish");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, " mem dump f myfile"); // download whole flashmem to file myfile
|
|
||||||
PrintAndLogEx(NORMAL, " mem dump p o 262015 l 128"); // display 128 bytes from offset 262015 (RSA sig)
|
|
||||||
PrintAndLogEx(NORMAL, " mem dump p f myfile o 241664 l 58"); // download and display 58 bytes from offset 241664 to file myfile
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_flashmem_wipe(void) {
|
|
||||||
|
|
||||||
PrintAndLogEx(WARNING, "[OBS] use with caution.");
|
|
||||||
PrintAndLogEx(NORMAL, "Wipe flash memory on device, which fills memory with 0xFF\n");
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, " Usage: mem wipe p <page>");
|
|
||||||
PrintAndLogEx(NORMAL, " p <page> : 0,1,2 page memory");
|
|
||||||
// PrintAndLogEx(NORMAL, " i : inital total wipe");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, " mem wipe p 0"); // wipes first page.
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_flashmem_info(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Collect signature and verify it from flash memory\n");
|
|
||||||
PrintAndLogEx(NORMAL, " Usage: mem info");
|
|
||||||
// PrintAndLogEx(NORMAL, " s : create a signature");
|
|
||||||
// PrintAndLogEx(NORMAL, " w : write signature to flash memory");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, " mem info");
|
|
||||||
// PrintAndLogEx(NORMAL, " mem info s");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CmdFlashmemSpiBaudrate(const char *Cmd) {
|
static int CmdFlashmemSpiBaudrate(const char *Cmd) {
|
||||||
|
|
||||||
char ctmp = tolower(param_getchar(Cmd, 0));
|
CLIParserContext *ctx;
|
||||||
if (strlen(Cmd) < 1 || ctmp == 'h') {
|
CLIParserInit(&ctx, "mem baudrate",
|
||||||
return usage_flashmem_spibaud();
|
"Set the baudrate for the SPI flash memory communications.\n"
|
||||||
|
"Reading Flash ID will virtually always fail under 48MHz setting.\n"
|
||||||
|
"Unless you know what you are doing, please stay at 24MHz.\n"
|
||||||
|
"If >= 24MHz, FASTREADS instead of READS instruction will be used.",
|
||||||
|
"mem baudrate --mhz 48"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_int1(NULL, "mhz", "<24|48>", "SPI baudrate in MHz"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
int br = arg_get_int_def(ctx, 1, -1);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (br == -1) {
|
||||||
|
PrintAndLogEx(ERR, "failed to get baudrate");
|
||||||
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10);
|
uint32_t baudrate = br * 1000000;
|
||||||
baudrate = baudrate * 1000000;
|
|
||||||
if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD) {
|
if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD) {
|
||||||
usage_flashmem_spibaud();
|
PrintAndLogEx(ERR, "wrong baudrate. Only 24 or 48 is allowed");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
SendCommandNG(CMD_FLASHMEM_SET_SPIBAUDRATE, (uint8_t *)&baudrate, sizeof(uint32_t));
|
SendCommandNG(CMD_FLASHMEM_SET_SPIBAUDRATE, (uint8_t *)&baudrate, sizeof(uint32_t));
|
||||||
|
@ -121,52 +62,50 @@ static int CmdFlashmemSpiBaudrate(const char *Cmd) {
|
||||||
|
|
||||||
static int CmdFlashMemLoad(const char *Cmd) {
|
static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
|
|
||||||
uint32_t start_index = 0;
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "mem load",
|
||||||
|
"Loads binary file into flash memory on device\n"
|
||||||
|
"Warning: mem area to be written must have been wiped first\n"
|
||||||
|
"( this is already taken care when loading dictionaries )",
|
||||||
|
"mem load -f myfile -> upload file myfile values at default offset 0\n"
|
||||||
|
"mem load -f myfile -o 1024 -> upload file myfile values at offset 1024\n"
|
||||||
|
"mem load -f mfc_default_keys -m -> upload MFC keys\n"
|
||||||
|
"mem load -f t55xx_default_pwds -t -> upload T55XX passwords\n"
|
||||||
|
"mem load -f iclass_default_keys -i -> upload iCLASS keys\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_int0("o", "offset", "<dec>", "offset in memory"),
|
||||||
|
arg_lit0("m", "mifare,mfc", "upload 6 bytes keys (mifare key dictionary)"),
|
||||||
|
arg_lit0("i", "iclass", "upload 8 bytes keys (iClass key dictionary)"),
|
||||||
|
arg_lit0("t", "t55xx", "upload 4 bytes keys (password dictionary)"),
|
||||||
|
arg_strx0("f", "file", "<filename>", "file name"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
int offset = arg_get_int_def(ctx, 1, 0);
|
||||||
|
bool is_mfc = arg_get_lit(ctx, 2);
|
||||||
|
bool is_iclass = arg_get_lit(ctx, 3);
|
||||||
|
bool is_t55xx = arg_get_lit(ctx, 4);
|
||||||
|
int fnlen = 0;
|
||||||
char filename[FILE_PATH_SIZE] = {0};
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
bool errors = false;
|
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
uint8_t cmdp = 0;
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
Dictionary_t d = DICTIONARY_NONE;
|
Dictionary_t d = DICTIONARY_NONE;
|
||||||
|
if (is_mfc) {
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
d = DICTIONARY_MIFARE;
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
PrintAndLogEx(INFO, "treating file as MIFARE Classic keys");
|
||||||
case 'h':
|
} else if (is_iclass) {
|
||||||
return usage_flashmem_load();
|
d = DICTIONARY_ICLASS;
|
||||||
case 'f':
|
PrintAndLogEx(INFO, "treating file as iCLASS keys");
|
||||||
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
|
} else if (is_t55xx) {
|
||||||
PrintAndLogEx(FAILED, "Filename too long");
|
d = DICTIONARY_T55XX;
|
||||||
errors = true;
|
PrintAndLogEx(INFO, "treating file as T55xx passwords");
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
d = DICTIONARY_MIFARE;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
d = DICTIONARY_T55XX;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
d = DICTIONARY_ICLASS;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Validations
|
|
||||||
if (errors || cmdp == 0) {
|
|
||||||
usage_flashmem_load();
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
size_t datalen = 0;
|
size_t datalen = 0;
|
||||||
uint32_t keycount = 0;
|
uint32_t keycount = 0;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
@ -174,7 +113,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
|
|
||||||
switch (d) {
|
switch (d) {
|
||||||
case DICTIONARY_MIFARE:
|
case DICTIONARY_MIFARE:
|
||||||
start_index = DEFAULT_MF_KEYS_OFFSET;
|
offset = DEFAULT_MF_KEYS_OFFSET;
|
||||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 6, &keycount);
|
res = loadFileDICTIONARY(filename, data + 2, &datalen, 6, &keycount);
|
||||||
if (res || !keycount) {
|
if (res || !keycount) {
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -189,7 +128,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
datalen += 2;
|
datalen += 2;
|
||||||
break;
|
break;
|
||||||
case DICTIONARY_T55XX:
|
case DICTIONARY_T55XX:
|
||||||
start_index = DEFAULT_T55XX_KEYS_OFFSET;
|
offset = DEFAULT_T55XX_KEYS_OFFSET;
|
||||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 4, &keycount);
|
res = loadFileDICTIONARY(filename, data + 2, &datalen, 4, &keycount);
|
||||||
if (res || !keycount) {
|
if (res || !keycount) {
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -204,7 +143,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
datalen += 2;
|
datalen += 2;
|
||||||
break;
|
break;
|
||||||
case DICTIONARY_ICLASS:
|
case DICTIONARY_ICLASS:
|
||||||
start_index = DEFAULT_ICLASS_KEYS_OFFSET;
|
offset = DEFAULT_ICLASS_KEYS_OFFSET;
|
||||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 8, &keycount);
|
res = loadFileDICTIONARY(filename, data + 2, &datalen, 8, &keycount);
|
||||||
if (res || !keycount) {
|
if (res || !keycount) {
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -253,13 +192,13 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
|
||||||
SendCommandOLD(CMD_FLASHMEM_WRITE, start_index + bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet);
|
SendCommandOLD(CMD_FLASHMEM_WRITE, offset + bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet);
|
||||||
|
|
||||||
bytes_remaining -= bytes_in_packet;
|
bytes_remaining -= bytes_in_packet;
|
||||||
bytes_sent += bytes_in_packet;
|
bytes_sent += bytes_in_packet;
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
conn.block_after_ACK = false;
|
conn.block_after_ACK = false;
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -276,54 +215,37 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
||||||
|
|
||||||
conn.block_after_ACK = false;
|
conn.block_after_ACK = false;
|
||||||
free(data);
|
free(data);
|
||||||
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu")" bytes to offset "_GREEN_("%u"), datalen, start_index);
|
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu")" bytes to offset "_GREEN_("%u"), datalen, offset);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdFlashMemDump(const char *Cmd) {
|
static int CmdFlashMemDump(const char *Cmd) {
|
||||||
|
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "mem dump",
|
||||||
|
"Dumps flash memory on device into a file or view in console",
|
||||||
|
"mem dump -f myfile -> download all flashmem to file\n"
|
||||||
|
"mem dump --view -o 262015 --len 128 -> display 128 bytes from offset 262015 (RSA sig)\n"
|
||||||
|
"mem dump --view -f myfile -o 241664 --len 58 -> display 58 bytes from offset 241664 and save to file"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_int0("o", "offset", "<dec>", "offset in memory"),
|
||||||
|
arg_int0("l", "len", "<dec>", "length"),
|
||||||
|
arg_lit0("v", "view", "view dump"),
|
||||||
|
arg_strx0("f", "file", "<filename>", "file name"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
int offset = arg_get_int_def(ctx, 1, 0);
|
||||||
|
int len = arg_get_int_def(ctx, 2, FLASH_MEM_MAX_SIZE);
|
||||||
|
bool view = arg_get_lit(ctx, 3);
|
||||||
|
int fnlen = 0;
|
||||||
char filename[FILE_PATH_SIZE] = {0};
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
uint8_t cmdp = 0;
|
CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
bool errors = false;
|
CLIParserFree(ctx);
|
||||||
bool print = false;
|
|
||||||
uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE;
|
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
|
||||||
case 'h':
|
|
||||||
return usage_flashmem_dump();
|
|
||||||
case 'l':
|
|
||||||
len = param_get32ex(Cmd, cmdp + 1, FLASH_MEM_MAX_SIZE, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
print = true;
|
|
||||||
cmdp += 1;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
//File handling
|
|
||||||
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
|
|
||||||
PrintAndLogEx(FAILED, "Filename too long");
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Validations
|
|
||||||
if (errors || cmdp == 0) {
|
|
||||||
usage_flashmem_dump();
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *dump = calloc(len, sizeof(uint8_t));
|
uint8_t *dump = calloc(len, sizeof(uint8_t));
|
||||||
if (!dump) {
|
if (!dump) {
|
||||||
|
@ -331,14 +253,15 @@ static int CmdFlashMemDump(const char *Cmd) {
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flashmem", len);
|
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flash memory", len);
|
||||||
if (!GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, 0, NULL, -1, true)) {
|
if (!GetFromDevice(FLASH_MEM, dump, len, offset, NULL, 0, NULL, -1, true)) {
|
||||||
PrintAndLogEx(FAILED, "ERROR; downloading from flashmemory");
|
PrintAndLogEx(FAILED, "ERROR; downloading from flash memory");
|
||||||
free(dump);
|
free(dump);
|
||||||
return PM3_EFLASH;
|
return PM3_EFLASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print) {
|
if (view) {
|
||||||
|
PrintAndLogEx(INFO, "---- " _CYAN_("data") " ---------------");
|
||||||
print_hex_break(dump, len, 32);
|
print_hex_break(dump, len, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,39 +273,32 @@ static int CmdFlashMemDump(const char *Cmd) {
|
||||||
free(dump);
|
free(dump);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdFlashMemWipe(const char *Cmd) {
|
static int CmdFlashMemWipe(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t cmdp = 0;
|
CLIParserContext *ctx;
|
||||||
bool errors = false;
|
CLIParserInit(&ctx, "mem wipe",
|
||||||
bool initalwipe = false;
|
"Wipe flash memory on device, which fills it with 0xFF\n"
|
||||||
uint8_t page = 0;
|
_WHITE_("[ ") _RED_("!!! OBS") " ] use with caution",
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
"mem wipe -p 0 -> wipes first page"
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
// "mem wipe -i -> inital total wipe"
|
||||||
case 'h':
|
);
|
||||||
return usage_flashmem_wipe();
|
|
||||||
case 'p':
|
|
||||||
page = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
if (page > 2) {
|
|
||||||
PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
initalwipe = true;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Validations
|
void *argtable[] = {
|
||||||
if (errors || cmdp == 0) {
|
arg_param_begin,
|
||||||
usage_flashmem_wipe();
|
arg_int0("p", NULL, "<dec>", "0,1,2 page memory"),
|
||||||
|
// arg_lit0("i", NULL, "inital total wipe"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
bool initalwipe = false;
|
||||||
|
int page = arg_get_int_def(ctx, 1, -1);
|
||||||
|
// initalwipe = arg_get_lit(ctx, 2);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (page < 0 || page > 2 ) {
|
||||||
|
PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,59 +309,51 @@ static int CmdFlashMemWipe(const char *Cmd) {
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* msg = "Flash WIPE ";
|
||||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||||
if (isok)
|
if (isok)
|
||||||
PrintAndLogEx(SUCCESS, "Flash WIPE ok");
|
PrintAndLogEx(SUCCESS, "%s ( " _GREEN_("ok")" )", msg);
|
||||||
else {
|
else {
|
||||||
PrintAndLogEx(FAILED, "Flash WIPE failed");
|
PrintAndLogEx(FAILED, "%s ( " _RED_("failed") " )", msg);
|
||||||
return PM3_EFLASH;
|
return PM3_EFLASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdFlashMemInfo(const char *Cmd) {
|
static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t sha_hash[20] = {0};
|
CLIParserContext *ctx;
|
||||||
mbedtls_rsa_context rsa;
|
CLIParserInit(&ctx, "mem info",
|
||||||
|
"Collect signature and verify it from flash memory",
|
||||||
|
"mem info"
|
||||||
|
// "mem info -s"
|
||||||
|
);
|
||||||
|
|
||||||
uint8_t cmdp = 0;
|
void *argtable[] = {
|
||||||
bool errors = false, shall_write = false, shall_sign = false;
|
arg_param_begin,
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
// arg_lit0("s", NULL, "create a signature"),
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
// arg_lit0("w", NULL, "write signature to flash memory"),
|
||||||
case 'h':
|
arg_param_end
|
||||||
return usage_flashmem_info();
|
};
|
||||||
case 's': {
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
shall_sign = true;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'w':
|
|
||||||
shall_write = true;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Validations
|
bool shall_sign = false, shall_write = false;
|
||||||
if (errors) {
|
// shall_sign = arg_get_lit(ctx, 1);
|
||||||
usage_flashmem_info();
|
// shall_write = arg_get_lit(ctx, 2);
|
||||||
return PM3_EINVARG;
|
CLIParserFree(ctx);
|
||||||
}
|
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
|
SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||||
if (!isok) {
|
if (isok == false) {
|
||||||
PrintAndLogEx(FAILED, "failed");
|
PrintAndLogEx(FAILED, "failed");
|
||||||
return PM3_EFLASH;
|
return PM3_EFLASH;
|
||||||
}
|
}
|
||||||
|
@ -455,15 +363,20 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
memcpy(&mem, (rdv40_validation_t *)resp.data.asBytes, sizeof(rdv40_validation_t));
|
memcpy(&mem, (rdv40_validation_t *)resp.data.asBytes, sizeof(rdv40_validation_t));
|
||||||
|
|
||||||
// Flash ID hash (sha1)
|
// Flash ID hash (sha1)
|
||||||
|
uint8_t sha_hash[20] = {0};
|
||||||
mbedtls_sha1(mem.flashid, sizeof(mem.flashid), sha_hash);
|
mbedtls_sha1(mem.flashid, sizeof(mem.flashid), sha_hash);
|
||||||
|
|
||||||
// print header
|
// print header
|
||||||
PrintAndLogEx(INFO, "\n--- Flash memory Information ---------");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
|
||||||
PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid)));
|
// PrintAndLogEx(INFO, "-----------------------------------------------------------------");
|
||||||
PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash)));
|
PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid)));
|
||||||
PrintAndLogEx(INFO, "RSA SIGNATURE |");
|
PrintAndLogEx(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
||||||
print_hex_break(mem.signature, sizeof(mem.signature), 32);
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA signature") " ---------------");
|
||||||
|
for (int i = 0; i < (sizeof(mem.signature) / 32); i++) {
|
||||||
|
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32));
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------
|
||||||
// RRG Public RSA Key
|
// RRG Public RSA Key
|
||||||
|
@ -473,7 +386,10 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
#define RSA_E "010001"
|
#define RSA_E "010001"
|
||||||
|
|
||||||
// public key modulus N
|
// public key modulus N
|
||||||
#define RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
|
#define RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF" \
|
||||||
|
"4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F" \
|
||||||
|
"9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33" \
|
||||||
|
"DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------
|
||||||
// Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
|
// Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
|
||||||
|
@ -516,9 +432,9 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
|
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
|
||||||
"A74206CEC169D74BF5A8C50D6F48EA08"
|
"A74206CEC169D74BF5A8C50D6F48EA08"
|
||||||
|
|
||||||
|
|
||||||
#define KEY_LEN 128
|
#define KEY_LEN 128
|
||||||
|
|
||||||
|
mbedtls_rsa_context rsa;
|
||||||
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
||||||
|
|
||||||
rsa.len = KEY_LEN;
|
rsa.len = KEY_LEN;
|
||||||
|
@ -532,13 +448,31 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
|
mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
|
||||||
mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
|
mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN);
|
|
||||||
|
|
||||||
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0);
|
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0);
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------");
|
||||||
|
|
||||||
|
char str_exp[10];
|
||||||
|
char str_pk[261];
|
||||||
|
size_t exlen = 0, pklen = 0;
|
||||||
|
mbedtls_mpi_write_string(&rsa.E, 16, str_exp, sizeof(str_exp), &exlen);
|
||||||
|
mbedtls_mpi_write_string(&rsa.N, 16, str_pk, sizeof(str_pk), &pklen);
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Len.................. %u", rsa.len);
|
||||||
|
PrintAndLogEx(INFO, "Exponent............. %s", str_exp);
|
||||||
|
PrintAndLogEx(INFO, "Public key modulus N");
|
||||||
|
PrintAndLogEx(INFO, " %.64s", str_pk);
|
||||||
|
PrintAndLogEx(INFO, " %.64s", str_pk + 64);
|
||||||
|
PrintAndLogEx(INFO, " %.64s", str_pk + 128);
|
||||||
|
PrintAndLogEx(INFO, " %.64s", str_pk + 192);
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
const char *msgkey = "RSA key validation... ";
|
||||||
if (is_keyok)
|
if (is_keyok)
|
||||||
PrintAndLogEx(SUCCESS, "RSA key validation ok");
|
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgkey);
|
||||||
else
|
else
|
||||||
PrintAndLogEx(FAILED, "RSA key validation failed");
|
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgkey);
|
||||||
|
|
||||||
//
|
//
|
||||||
uint8_t from_device[KEY_LEN];
|
uint8_t from_device[KEY_LEN];
|
||||||
|
@ -554,10 +488,11 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
if (shall_sign) {
|
if (shall_sign) {
|
||||||
|
|
||||||
int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
|
int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
|
||||||
|
const char *msgsign = "RSA signing.......... ";
|
||||||
if (is_signed == 0)
|
if (is_signed == 0)
|
||||||
PrintAndLogEx(SUCCESS, "RSA Signing ok");
|
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgsign);
|
||||||
else
|
else
|
||||||
PrintAndLogEx(FAILED, "RSA Signing failed");
|
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgsign);
|
||||||
|
|
||||||
if (shall_write) {
|
if (shall_write) {
|
||||||
// save to mem
|
// save to mem
|
||||||
|
@ -574,29 +509,33 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintAndLogEx(INFO, "Signed | ");
|
PrintAndLogEx(INFO, "Signed");
|
||||||
print_hex_break(sign, sizeof(sign), 32);
|
for (int i = 0; i < (sizeof(sign) / 32); i++) {
|
||||||
|
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify (public key)
|
// Verify (public key)
|
||||||
int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device);
|
int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device);
|
||||||
|
const char *msgverify = "RSA verification..... ";
|
||||||
if (is_verified == 0)
|
if (is_verified == 0)
|
||||||
PrintAndLogEx(SUCCESS, "RSA Verification ok");
|
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgverify);
|
||||||
else
|
else
|
||||||
PrintAndLogEx(FAILED, "RSA Verification failed");
|
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgverify);
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation [rdv40]"},
|
{"baudrate", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate"},
|
||||||
{"spibaud", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate [rdv40]"},
|
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation"},
|
||||||
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information [rdv40]"},
|
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"},
|
||||||
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory [rdv40]"},
|
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory"},
|
||||||
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory [rdv40]"},
|
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"},
|
||||||
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory [rdv40]"},
|
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ static uint16_t get_sw(uint8_t *d, uint8_t n) {
|
||||||
return d[n] * 0x0100 + d[n + 1];
|
return d[n] * 0x0100 + d[n + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool wait_cmd_14b(bool verbose) {
|
static bool wait_cmd_14b(bool verbose, bool is_select) {
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||||
|
@ -71,6 +71,23 @@ static bool wait_cmd_14b(bool verbose) {
|
||||||
uint16_t len = (resp.oldarg[1] & 0xFFFF);
|
uint16_t len = (resp.oldarg[1] & 0xFFFF);
|
||||||
uint8_t *data = resp.data.asBytes;
|
uint8_t *data = resp.data.asBytes;
|
||||||
|
|
||||||
|
// handle select responses
|
||||||
|
if (is_select) {
|
||||||
|
|
||||||
|
// 0: OK; -1: attrib fail; -2:crc fail
|
||||||
|
int status = (int)resp.oldarg[0];
|
||||||
|
if (status == 0) {
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
PrintAndLogEx(SUCCESS, "len %u | %s", len, sprint_hex(data, len));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle raw bytes responses
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
|
|
||||||
if (len >= 3) {
|
if (len >= 3) {
|
||||||
|
@ -121,12 +138,14 @@ static int CmdHF14BSim(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t pupi[4];
|
uint8_t pupi[4];
|
||||||
int n = 0;
|
int n = 0;
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 1), pupi, sizeof(pupi), &n);
|
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), pupi, sizeof(pupi), &n);
|
||||||
|
if (res) {
|
||||||
|
PrintAndLogEx(FAILED, "failed to read pupi");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi));
|
SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi));
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,27 +180,26 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf 14b raw",
|
CLIParserInit(&ctx, "hf 14b raw",
|
||||||
"Sends raw bytes to card ",
|
"Sends raw bytes to card ",
|
||||||
"hf 14b raw -s -c -k 0200a40400\n"
|
"hf 14b raw -cks --data 0200a40400 -> standard select\n"
|
||||||
"hf 14b raw --sr -c -k 0200a40400\n"
|
"hf 14b raw -ck --sr --data 0200a40400 -> SRx select\n"
|
||||||
"hf 14b raw --cts -c -k 0200a40400\n"
|
"hf 14b raw -ck --cts --data 0200a40400 -> C-ticket select\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
|
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
|
||||||
arg_lit0("s", "std", "activate field and select standard card"),
|
arg_lit0("s", "std", "activate field and select standard card"),
|
||||||
arg_lit0(NULL, "sr", "activate field and select SRx ST"),
|
arg_lit0(NULL, "sr", "activate field and select SRx ST"),
|
||||||
arg_lit0(NULL, "cts", "activate field and select ASK C-ticket"),
|
arg_lit0(NULL, "cts", "activate field and select ASK C-ticket"),
|
||||||
arg_lit0("c", "crc", "calculate and append CRC"),
|
arg_lit0("c", "crc", "calculate and append CRC"),
|
||||||
arg_lit0("r", "noresponse", "do not read response"),
|
arg_lit0("r", "noresponse", "do not read response"),
|
||||||
arg_int0("t", "timeout", "decimal", "timeout in ms"),
|
arg_int0("t", "timeout", "<dec>", "timeout in ms"),
|
||||||
arg_lit0("v", "verbose", "verbose"),
|
arg_lit0("v", "verbose", "verbose"),
|
||||||
arg_strx0(NULL, NULL, "<data (hex)>", "bytes to send"),
|
arg_strx0("d", "data", "<hex>", "data, bytes to send"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
bool select = false;
|
|
||||||
bool keep_field_on = arg_get_lit(ctx, 1);
|
bool keep_field_on = arg_get_lit(ctx, 1);
|
||||||
bool select_std = arg_get_lit(ctx, 2);
|
bool select_std = arg_get_lit(ctx, 2);
|
||||||
bool select_sr = arg_get_lit(ctx, 3);
|
bool select_sr = arg_get_lit(ctx, 3);
|
||||||
|
@ -197,25 +215,25 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (select_std) {
|
if (select_std) {
|
||||||
select = true;
|
flags |= (ISO14B_SELECT_STD | ISO14B_CLEARTRACE);
|
||||||
flags |= ISO14B_SELECT_STD;
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "using standard select");
|
PrintAndLogEx(INFO, "using standard select");
|
||||||
} else if (select_sr) {
|
} else if (select_sr) {
|
||||||
select = true;
|
flags |= (ISO14B_SELECT_SR | ISO14B_CLEARTRACE);
|
||||||
flags |= ISO14B_SELECT_SR;
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "using SRx ST select");
|
PrintAndLogEx(INFO, "using ST/SRx select");
|
||||||
} else if (select_cts) {
|
} else if (select_cts) {
|
||||||
select = true;
|
flags |= (ISO14B_SELECT_CTS | ISO14B_CLEARTRACE);
|
||||||
flags |= ISO14B_SELECT_CTS;
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "using ASK C-ticket select");
|
PrintAndLogEx(INFO, "using ASK/C-ticket select");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
|
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
|
||||||
int datalen = 0;
|
int datalen = 0;
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 9), data, sizeof(data), &datalen);
|
int res = CLIParamHexToBuf(arg_get_str(ctx, 9), data, sizeof(data), &datalen);
|
||||||
|
if (res && verbose) {
|
||||||
|
PrintAndLogEx(INFO, "called with no raw bytes");
|
||||||
|
}
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
uint32_t time_wait = 0;
|
uint32_t time_wait = 0;
|
||||||
|
@ -244,18 +262,33 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, datalen, time_wait, data, datalen);
|
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, datalen, time_wait, data, datalen);
|
||||||
if (read_reply == false) {
|
if (read_reply == false) {
|
||||||
|
clearCommandBuffer();
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
// get back iso14b_card_select_t, don't print it.
|
// Select, device will send back iso14b_card_select_t, don't print it.
|
||||||
if (select) {
|
if (select_std) {
|
||||||
success = wait_cmd_14b(verbose);
|
success = wait_cmd_14b(verbose, true);
|
||||||
|
if (verbose && success)
|
||||||
|
PrintAndLogEx(SUCCESS, "Got response for standard select");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (select_sr) {
|
||||||
|
success = wait_cmd_14b(verbose, true);
|
||||||
|
if (verbose && success)
|
||||||
|
PrintAndLogEx(SUCCESS, "Got response for ST/SRx select");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (select_cts) {
|
||||||
|
success = wait_cmd_14b(verbose, true);
|
||||||
|
if (verbose && success)
|
||||||
|
PrintAndLogEx(SUCCESS, "Got response for ASK/C-ticket select");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get back response from the raw bytes you sent.
|
// get back response from the raw bytes you sent.
|
||||||
if (success && datalen > 0) {
|
if (success && datalen > 0) {
|
||||||
wait_cmd_14b(true);
|
wait_cmd_14b(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
@ -1022,7 +1055,7 @@ static int CmdHF14BWriteSri(const char *Cmd) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(str, "-ss -c %02x %02x %02x %02x %02x %02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]);
|
sprintf(str, "--ss -c %02x %02x %02x %02x %02x %02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]);
|
||||||
return CmdHF14BCmdRaw(str);
|
return CmdHF14BCmdRaw(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1525,10 +1558,10 @@ static int CmdHF14BAPDU(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf 14b apdu",
|
CLIParserInit(&ctx, "hf 14b apdu",
|
||||||
"Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). works with all apdu types from ISO 7816-4:2013",
|
"Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). works with all apdu types from ISO 7816-4:2013",
|
||||||
"hf 14b apdu -s 94a40800043f000002\n"
|
"hf 14b apdu -s --hex 94a40800043f000002\n"
|
||||||
"hf 14b apdu -sd 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
|
"hf 14b apdu -sd --hex 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
|
||||||
"hf 14b apdu -sm 00A40400 325041592E5359532E4444463031 -l 256 -> encode standard apdu\n"
|
"hf 14b apdu -sm 00A40400 -l 256 --hex 325041592E5359532E4444463031 -> encode standard apdu\n"
|
||||||
"hf 14b apdu -sm 00A40400 325041592E5359532E4444463031 -el 65536 -> encode extended apdu\n");
|
"hf 14b apdu -sm 00A40400 -el 65536 --hex 325041592E5359532E4444463031 -> encode extended apdu\n");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -1536,10 +1569,10 @@ static int CmdHF14BAPDU(const char *Cmd) {
|
||||||
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
|
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
|
||||||
arg_lit0("t", "tlv", "executes TLV decoder if it possible"),
|
arg_lit0("t", "tlv", "executes TLV decoder if it possible"),
|
||||||
arg_lit0("d", "decode", "decode apdu request if it possible"),
|
arg_lit0("d", "decode", "decode apdu request if it possible"),
|
||||||
arg_str0("m", "make", "<head (CLA INS P1 P2) hex>", "make apdu with head from this field and data from data field. Must be 4 bytes length: <CLA INS P1 P2>"),
|
arg_str0("m", "make", "<hex>", "make apdu with head from this field and data from data field. Must be 4 bytes length: <CLA INS P1 P2>"),
|
||||||
arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
|
arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
|
||||||
arg_int0("l", "le", "<Le (int)>", "Le apdu parameter if `m` parameter included"),
|
arg_int0("l", "le", "<int>", "Le apdu parameter if `m` parameter included"),
|
||||||
arg_strx1(NULL, NULL, "<APDU (hex) | data (hex)>", "data if `m` parameter included"),
|
arg_strx1(NULL, "hex", "<hex>", "<APDU | data> if `m` parameter included"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
|
@ -325,8 +325,8 @@ static int cmd_hf_st_sim(const char *Cmd) {
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
if (uidlen != 7) {
|
if (uidlen != 7) {
|
||||||
PrintAndLogEx(ERR, "UID must be 7 hex bytes");
|
PrintAndLogEx(ERR, "UID must be 7 hex bytes");
|
||||||
|
@ -350,12 +350,12 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_str0("p", "password", "<hex>", "16 byte read password"),
|
arg_str0("p", "pwd", "<hex>", "16 byte read password"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
CLIGetHexWithReturn(ctx, 1, pwd, &pwdlen);
|
CLIGetHexWithReturn(ctx, 1, pwd, &pwdlen);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
if (pwdlen == 0) {
|
if (pwdlen == 0) {
|
||||||
with_pwd = false;
|
with_pwd = false;
|
||||||
|
@ -483,13 +483,10 @@ static int cmd_hf_st_protect(const char *Cmd) {
|
||||||
disable_protection = arg_get_lit(ctx, 2);
|
disable_protection = arg_get_lit(ctx, 2);
|
||||||
read_protection = arg_get_lit(ctx, 3);
|
read_protection = arg_get_lit(ctx, 3);
|
||||||
write_protection = arg_get_lit(ctx, 4);
|
write_protection = arg_get_lit(ctx, 4);
|
||||||
|
|
||||||
CLIGetHexWithReturn(ctx, 5, pwd, &pwdlen);
|
CLIGetHexWithReturn(ctx, 5, pwd, &pwdlen);
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
//Validations
|
//Validations
|
||||||
|
|
||||||
if (enable_protection && disable_protection) {
|
if (enable_protection && disable_protection) {
|
||||||
PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both");
|
PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
|
@ -625,14 +622,12 @@ static int cmd_hf_st_pwd(const char *Cmd) {
|
||||||
|
|
||||||
change_read_password = arg_get_lit(ctx, 1);
|
change_read_password = arg_get_lit(ctx, 1);
|
||||||
change_write_password = arg_get_lit(ctx, 2);
|
change_write_password = arg_get_lit(ctx, 2);
|
||||||
|
|
||||||
CLIGetHexWithReturn(ctx, 3, pwd, &pwdlen);
|
CLIGetHexWithReturn(ctx, 3, pwd, &pwdlen);
|
||||||
|
|
||||||
CLIGetHexWithReturn(ctx, 4, newpwd, &newpwdlen);
|
CLIGetHexWithReturn(ctx, 4, newpwd, &newpwdlen);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
if (change_read_password && change_write_password) {
|
if (change_read_password && change_write_password) {
|
||||||
PrintAndLogEx(ERR, "Must specify either read or write, not both");
|
PrintAndLogEx(ERR, "Must specify either read or write, not both");
|
||||||
CLIParserFree(ctx);
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
} else {
|
} else {
|
||||||
if (change_read_password) {
|
if (change_read_password) {
|
||||||
|
@ -643,8 +638,6 @@ static int cmd_hf_st_pwd(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
|
||||||
|
|
||||||
if (pwdlen != 16) {
|
if (pwdlen != 16) {
|
||||||
PrintAndLogEx(ERR, "Original write password must be 16 hex bytes");
|
PrintAndLogEx(ERR, "Original write password must be 16 hex bytes");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
|
@ -727,9 +720,7 @@ static int cmd_hf_st_pwd(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, " %s password changed", ((changePwd[2] & 0x01) == 0x01) ? _YELLOW_("read") : _YELLOW_("write"));
|
PrintAndLogEx(SUCCESS, " %s password changed", ((changePwd[2] & 0x01) == 0x01) ? _YELLOW_("read") : _YELLOW_("write"));
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_hf_st_list(const char *Cmd) {
|
static int cmd_hf_st_list(const char *Cmd) {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
#include "commonutil.h" // ARRAYLEN
|
#include "commonutil.h" // ARRAYLEN
|
||||||
|
#include "cliparser.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "cmddata.h" //for g_debugMode, demodbuff cmds
|
#include "cmddata.h" //for g_debugMode, demodbuff cmds
|
||||||
|
@ -43,70 +44,6 @@
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_hid_watch(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Enables HID compatible reader mode printing details.");
|
|
||||||
PrintAndLogEx(NORMAL, "By default, values are printed and logged until the button is pressed or another USB command is issued.");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf hid watch");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid watch"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_lf_hid_sim(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Enables simulation of HID card with card number.");
|
|
||||||
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf hid sim [h] [ID]");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - This help");
|
|
||||||
PrintAndLogEx(NORMAL, " ID - HID id");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid sim 2006ec0c86"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_lf_hid_clone(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Clone HID to T55x7. " _BLUE_("Tag must be on antenna!"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf hid clone [h] [l] ID");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - This help");
|
|
||||||
PrintAndLogEx(NORMAL, " l - 84bit ID");
|
|
||||||
PrintAndLogEx(NORMAL, " ID - HID id");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid clone 2006ec0c86"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid clone l 2006ec0c86"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_lf_hid_brute(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Enables bruteforce of HID readers with specified facility code.");
|
|
||||||
PrintAndLogEx(NORMAL, "This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step");
|
|
||||||
PrintAndLogEx(NORMAL, "if cardnumber is not given, it starts with 1 and goes up to 65535");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf hid brute [h] [v] w <format> [<field> (decimal)>] [up|down] {...}");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
|
||||||
PrintAndLogEx(NORMAL, " w <format> : see " _YELLOW_("`wiegand list`") " for available formats");
|
|
||||||
PrintAndLogEx(NORMAL, " f <facility-code> : facility code");
|
|
||||||
PrintAndLogEx(NORMAL, " c <cardnumber> : card number to start with");
|
|
||||||
PrintAndLogEx(NORMAL, " i <issuelevel> : issue level");
|
|
||||||
PrintAndLogEx(NORMAL, " o <oem> : OEM code");
|
|
||||||
PrintAndLogEx(NORMAL, " d <delay> : delay betweens attempts in ms. Default 1000ms");
|
|
||||||
PrintAndLogEx(NORMAL, " v : verbose logging, show all tries");
|
|
||||||
PrintAndLogEx(NORMAL, " up : direction to increment card number. (default is both directions)");
|
|
||||||
PrintAndLogEx(NORMAL, " down : direction to decrement card number. (default is both directions)");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute w H10301 f 224"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute w H10301 f 21 d 2000"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute v w H10301 f 21 c 200 d 2000"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sending three times. Didn't seem to break the previous sim?
|
// sending three times. Didn't seem to break the previous sim?
|
||||||
static int sendPing(void) {
|
static int sendPing(void) {
|
||||||
SendCommandNG(CMD_PING, NULL, 0);
|
SendCommandNG(CMD_PING, NULL, 0);
|
||||||
|
@ -276,8 +213,20 @@ static int CmdHIDRead(const char *Cmd) {
|
||||||
// this read loops on device side.
|
// this read loops on device side.
|
||||||
// uses the demod in lfops.c
|
// uses the demod in lfops.c
|
||||||
static int CmdHIDWatch(const char *Cmd) {
|
static int CmdHIDWatch(const char *Cmd) {
|
||||||
uint8_t c = tolower(param_getchar(Cmd, 0));
|
CLIParserContext *ctx;
|
||||||
if (c == 'h') return usage_lf_hid_watch();
|
|
||||||
|
CLIParserInit(&ctx, "lf hid watch",
|
||||||
|
"Enables HID compatible reader mode printing details.\n"
|
||||||
|
"By default, values are printed and logged until the button is pressed or another USB command is issued.\n",
|
||||||
|
"lf hid watch"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Watching for HID Prox cards - place tag on antenna");
|
PrintAndLogEx(SUCCESS, "Watching for HID Prox cards - place tag on antenna");
|
||||||
PrintAndLogEx(INFO, "Press pm3-button to stop reading cards");
|
PrintAndLogEx(INFO, "Press pm3-button to stop reading cards");
|
||||||
|
@ -290,28 +239,52 @@ static int CmdHIDWatch(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHIDSim(const char *Cmd) {
|
static int CmdHIDSim(const char *Cmd) {
|
||||||
|
int idlen = 0;
|
||||||
|
uint8_t id[10] = {0};
|
||||||
lf_hidsim_t payload;
|
lf_hidsim_t payload;
|
||||||
payload.longFMT = 0;
|
payload.longFMT = 0;
|
||||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||||
uint32_t n = 0, i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
|
CLIParserContext *ctx;
|
||||||
if (strlen(Cmd) == 0 || ctmp == 'h') return usage_lf_hid_sim();
|
CLIParserInit(&ctx, "lf hid sim",
|
||||||
|
"Enables simulation of HID card with card number.",
|
||||||
|
"lf hid sim 2006ec0c86"
|
||||||
|
);
|
||||||
|
|
||||||
if (strchr(Cmd, 'l') != 0) {
|
void *argtable[] = {
|
||||||
i++;
|
arg_param_begin,
|
||||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
arg_lit0("l", "long", "Simulate HID tag with long ID"),
|
||||||
|
arg_str1(NULL, NULL, "<hex>", "HID tag ID"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
bool long_id = arg_get_lit(ctx, 1);
|
||||||
|
|
||||||
|
CLIGetHexWithReturn(ctx, 2, id, &idlen);
|
||||||
|
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (long_id) {
|
||||||
|
for (i=0; i < idlen; ++i) {
|
||||||
hi2 = (hi2 << 4) | (hi >> 28);
|
hi2 = (hi2 << 4) | (hi >> 28);
|
||||||
hi = (hi << 4) | (lo >> 28);
|
hi = (hi << 4) | (lo >> 28);
|
||||||
lo = (lo << 4) | (n & 0xf);
|
lo = (lo << 4) | (id[i] >> 4); //get first 4 bits
|
||||||
}
|
|
||||||
|
|
||||||
|
hi2 = (hi2 << 4) | (hi >> 28);
|
||||||
|
hi = (hi << 4) | (lo >> 28);
|
||||||
|
lo = (lo << 4) | (id[i] & 0xf); //get last 4 bits
|
||||||
|
}
|
||||||
PrintAndLogEx(INFO, "Simulating HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo);
|
PrintAndLogEx(INFO, "Simulating HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo);
|
||||||
payload.longFMT = 1;
|
payload.longFMT = 1;
|
||||||
} else {
|
} else {
|
||||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
for (i=0; i < idlen; ++i) {
|
||||||
hi = (hi << 4) | (lo >> 28);
|
hi = (hi << 4) | (lo >> 28);
|
||||||
lo = (lo << 4) | (n & 0xf);
|
lo = (lo << 4) | (id[i] >> 4); //get first 4 bits
|
||||||
|
|
||||||
|
hi = (hi << 4) | (lo >> 28);
|
||||||
|
lo = (lo << 4) | (id[i] & 0xf); //get last 4 bits
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "Simulating HID tag with ID: " _GREEN_("%x%08x"), hi, lo);
|
PrintAndLogEx(SUCCESS, "Simulating HID tag with ID: " _GREEN_("%x%08x"), hi, lo);
|
||||||
hi2 = 0;
|
hi2 = 0;
|
||||||
|
@ -334,28 +307,55 @@ static int CmdHIDSim(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHIDClone(const char *Cmd) {
|
static int CmdHIDClone(const char *Cmd) {
|
||||||
|
int idlen = 0;
|
||||||
|
uint8_t id[10] = {0};
|
||||||
|
|
||||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||||
uint32_t n = 0, i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "lf hid clone",
|
||||||
|
"Clone HID to T55x7. Tag must be on antenna!",
|
||||||
|
"lf hid clone 2006ec0c86\n"
|
||||||
|
"lf hid clone -l 2006ec0c86"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_lit0("l", "long", "84bit HID long ID"),
|
||||||
|
arg_str1(NULL, NULL, "<hex>", "HID tag ID"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
bool long_id = arg_get_lit(ctx, 1);
|
||||||
|
|
||||||
|
CLIGetHexWithReturn(ctx, 2, id, &idlen);
|
||||||
|
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
|
|
||||||
if (strlen(Cmd) == 0 || ctmp == 'h') return usage_lf_hid_clone();
|
|
||||||
uint8_t longid[1] = {0};
|
uint8_t longid[1] = {0};
|
||||||
if (strchr(Cmd, 'l') != 0) {
|
|
||||||
i++;
|
if (long_id) {
|
||||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
for (i=0; i < idlen; ++i) {
|
||||||
hi2 = (hi2 << 4) | (hi >> 28);
|
hi2 = (hi2 << 4) | (hi >> 28);
|
||||||
hi = (hi << 4) | (lo >> 28);
|
hi = (hi << 4) | (lo >> 28);
|
||||||
lo = (lo << 4) | (n & 0xf);
|
lo = (lo << 4) | (id[i] >> 4); //get first 4 bits
|
||||||
}
|
|
||||||
|
|
||||||
|
hi2 = (hi2 << 4) | (hi >> 28);
|
||||||
|
hi = (hi << 4) | (lo >> 28);
|
||||||
|
lo = (lo << 4) | (id[i] & 0xf); //get last 4 bits
|
||||||
|
}
|
||||||
PrintAndLogEx(INFO, "Preparing to clone HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo);
|
PrintAndLogEx(INFO, "Preparing to clone HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo);
|
||||||
|
|
||||||
longid[0] = 1;
|
longid[0] = 1;
|
||||||
} else {
|
} else {
|
||||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
for (i=0; i < idlen; ++i) {
|
||||||
hi = (hi << 4) | (lo >> 28);
|
hi = (hi << 4) | (lo >> 28);
|
||||||
lo = (lo << 4) | (n & 0xf);
|
lo = (lo << 4) | (id[i] >> 4); //get first 4 bits
|
||||||
|
|
||||||
|
hi = (hi << 4) | (lo >> 28);
|
||||||
|
lo = (lo << 4) | (id[i] & 0xf); //get last 4 bits
|
||||||
}
|
}
|
||||||
PrintAndLogEx(INFO, "Preparing to clone HID tag with ID: " _GREEN_("%x%08x"), hi, lo);
|
PrintAndLogEx(INFO, "Preparing to clone HID tag with ID: " _GREEN_("%x%08x"), hi, lo);
|
||||||
hi2 = 0;
|
hi2 = 0;
|
||||||
|
@ -385,82 +385,63 @@ static int CmdHIDClone(const char *Cmd) {
|
||||||
|
|
||||||
static int CmdHIDBrute(const char *Cmd) {
|
static int CmdHIDBrute(const char *Cmd) {
|
||||||
|
|
||||||
bool errors = false, verbose = false;
|
|
||||||
uint32_t delay = 1000;
|
uint32_t delay = 1000;
|
||||||
uint8_t cmdp = 0;
|
|
||||||
int format_idx = -1;
|
int format_idx = -1;
|
||||||
int direction = 0;
|
int direction = 0;
|
||||||
char format[16] = {0};
|
uint8_t format[16] = {0};
|
||||||
|
int formatLen;
|
||||||
|
|
||||||
wiegand_card_t cn_hi, cn_low;
|
wiegand_card_t cn_hi, cn_low;
|
||||||
memset(&cn_hi, 0, sizeof(wiegand_card_t));
|
memset(&cn_hi, 0, sizeof(wiegand_card_t));
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "lf hid brute",
|
||||||
|
"Enables bruteforce of HID readers with specified facility code.\n"
|
||||||
|
"This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step\n"
|
||||||
|
"if cardnumber is not given, it starts with 1 and goes up to 65535",
|
||||||
|
"lf hid brute -w H10301 -f 224\n"
|
||||||
|
"lf hid brute -w H10301 -f 21 -d 2000\n"
|
||||||
|
"lf hid brute -v -w H10301 -f 21 -c 200 -d 2000\n"
|
||||||
|
);
|
||||||
|
|
||||||
char s[10] = {0};
|
void *argtable[] = {
|
||||||
if (param_getstr(Cmd, cmdp, s, sizeof(s)) > 0) {
|
arg_param_begin,
|
||||||
if (strlen(s) > 1) {
|
arg_lit0("v", "verbose", "verbose logging, show all tries"),
|
||||||
str_lower((char *)s);
|
arg_str1("w", "wiegand", "format", "see " _YELLOW_("`wiegand list`") " for available formats"),
|
||||||
if (str_startswith(s, "up")) {
|
arg_int0("f", "fn", "dec", "facility code"),
|
||||||
direction = 1;
|
arg_int0("c", "cn", "dec", "card number to start with"),
|
||||||
} else if (str_startswith(s, "do")) {
|
arg_int0("i", NULL, "dec", "issue level"),
|
||||||
direction = 2;
|
arg_int0("o", "oem", "dec", "OEM code"),
|
||||||
}
|
arg_int0("d", "delay", "dec", "delay betweens attempts in ms. Default 1000ms"),
|
||||||
cmdp++;
|
arg_lit0(NULL, "up", "direction to increment card number. (default is both directions)"),
|
||||||
continue;
|
arg_lit0(NULL, "down", "direction to decrement card number. (default is both directions)"),
|
||||||
}
|
arg_param_end
|
||||||
}
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
bool verbose = arg_get_lit(ctx, 1);
|
||||||
case 'h':
|
|
||||||
return usage_lf_hid_brute();
|
|
||||||
case 'w':
|
|
||||||
param_getstr(Cmd, cmdp + 1, format, sizeof(format));
|
|
||||||
format_idx = HIDFindCardFormat(format);
|
|
||||||
if (format_idx == -1) {
|
|
||||||
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
|
|
||||||
errors = true;
|
|
||||||
}
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
cn_hi.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
// delay between attemps, defaults to 1000ms.
|
|
||||||
delay = param_get32ex(Cmd, cmdp + 1, 1000, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
cn_hi.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
cn_hi.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
cn_hi.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
verbose = true;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter: " _YELLOW_("'%c'"), param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
CLIGetStrWithReturn(ctx, 2, format, &formatLen);
|
||||||
|
|
||||||
|
format_idx = HIDFindCardFormat((char*) format);
|
||||||
if (format_idx == -1) {
|
if (format_idx == -1) {
|
||||||
PrintAndLogEx(ERR, "You must select a wiegand format. See " _YELLOW_("`wiegand list`") " for available formats\n");
|
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
|
||||||
errors = true;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors) return usage_lf_hid_brute();
|
cn_hi.FacilityCode = arg_get_int_def(ctx, 3, 0);
|
||||||
|
cn_hi.CardNumber = arg_get_int_def(ctx, 4, 0);
|
||||||
|
cn_hi.IssueLevel = arg_get_int_def(ctx, 5, 0);
|
||||||
|
cn_hi.OEM = arg_get_int_def(ctx, 6, 0);
|
||||||
|
delay = arg_get_int_def(ctx, 7, 1000);
|
||||||
|
|
||||||
|
if (arg_get_lit(ctx, 8) && arg_get_lit(ctx, 9)) {
|
||||||
|
direction = 0;
|
||||||
|
} else if (arg_get_lit(ctx, 8)) {
|
||||||
|
direction = 1;
|
||||||
|
} else if (arg_get_lit(ctx, 9)) {
|
||||||
|
direction = 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(INFO, "Wiegand format#.. %i", format_idx);
|
PrintAndLogEx(INFO, "Wiegand format#.. %i", format_idx);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "commonutil.h" // ARRAYLEN
|
#include "commonutil.h" // ARRAYLEN
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
|
#include "cliparser.h"
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmddata.h"
|
#include "cmddata.h"
|
||||||
|
@ -26,43 +27,6 @@
|
||||||
#include "cmdlft55xx.h" // verifywrite
|
#include "cmdlft55xx.h" // verifywrite
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_keri_clone(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "clone a KERI tag to a T55x7 or Q5/T5555 tag\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf keri clone [h] <id> <Q5>");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage extended: lf keri clone [h] t <m|i> [f <fc>] [c <cardnumber>] <Q5>");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
|
||||||
PrintAndLogEx(NORMAL, " <id> : Keri Internal ID");
|
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
|
|
||||||
// New format
|
|
||||||
PrintAndLogEx(NORMAL, " <t> [m|i] : Type m - MS, i - Internal ID");
|
|
||||||
PrintAndLogEx(NORMAL, " <f> <fc> : Facility Code");
|
|
||||||
PrintAndLogEx(NORMAL, " <c> <cn> : Card Number");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone 112233"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone t i fc 6 cn 12345"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone t m f 6 c 12345"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int usage_lf_keri_sim(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Enables simulation of KERI card with specified card number.");
|
|
||||||
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf keri sim [h] <id>");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
|
||||||
PrintAndLogEx(NORMAL, " <id> : Keri Internal ID");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri sim 112233"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum {Scramble = 0, Descramble = 1} KeriMSScramble_t;
|
typedef enum {Scramble = 0, Descramble = 1} KeriMSScramble_t;
|
||||||
|
|
||||||
static int CmdKeriMSScramble(KeriMSScramble_t Action, uint32_t *FC, uint32_t *ID, uint32_t *CardID) {
|
static int CmdKeriMSScramble(KeriMSScramble_t Action, uint32_t *FC, uint32_t *ID, uint32_t *CardID) {
|
||||||
|
@ -222,8 +186,9 @@ static int CmdKeriRead(const char *Cmd) {
|
||||||
static int CmdKeriClone(const char *Cmd) {
|
static int CmdKeriClone(const char *Cmd) {
|
||||||
|
|
||||||
bool q5 = false;
|
bool q5 = false;
|
||||||
uint8_t cmdidx = 0;
|
|
||||||
char keritype = 'i'; // default to internalid
|
uint8_t keritype[2] = {'i'}; // default to internalid
|
||||||
|
int typeLen = 0;
|
||||||
uint32_t fc = 0;
|
uint32_t fc = 0;
|
||||||
uint32_t cid = 0;
|
uint32_t cid = 0;
|
||||||
uint32_t internalid = 0;
|
uint32_t internalid = 0;
|
||||||
|
@ -240,42 +205,35 @@ static int CmdKeriClone(const char *Cmd) {
|
||||||
// dynamic bitrate used
|
// dynamic bitrate used
|
||||||
blocks[0] |= 0xF << 18;
|
blocks[0] |= 0xF << 18;
|
||||||
|
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
CLIParserContext *ctx;
|
||||||
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_clone();
|
CLIParserInit(&ctx, "lf keri clone",
|
||||||
|
"clone a KERI tag to a T55x7 or Q5/T5555 tag",
|
||||||
|
"lf keri clone -t i --id 12345\n"
|
||||||
|
"lf keri clone -t m --fc 6 --id 12345\n");
|
||||||
|
|
||||||
// Assume old format for backwards compatibility and only parameter is the internal id
|
void *argtable[] = {
|
||||||
cid = param_get32ex(Cmd, 0, 0, 10);
|
arg_param_begin,
|
||||||
|
arg_lit0("q", "q5", "specify writing to Q5/T5555 tag"),
|
||||||
|
arg_str0("t", "type", "<m|i>", "Type m - MS, i - Internal ID"),
|
||||||
|
arg_int0(NULL, "fc", "<dec>", "Facility Code"),
|
||||||
|
arg_int1(NULL, "id", "<dec>", "Keri ID"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
// find other options
|
if (arg_get_lit(ctx, 1)) {
|
||||||
while (param_getchar(Cmd, cmdidx) != 0x00) { // && !errors) {
|
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
|
||||||
switch (tolower(param_getchar(Cmd, cmdidx))) {
|
q5 = true;
|
||||||
case 'h': // help
|
|
||||||
return usage_lf_keri_clone();
|
|
||||||
case 't': // format type
|
|
||||||
keritype = tolower(param_getchar(Cmd, cmdidx + 1));
|
|
||||||
cmdidx += 2;
|
|
||||||
break;
|
|
||||||
case 'f': // fc
|
|
||||||
fc = param_get32ex(Cmd, cmdidx + 1, 0, 10);
|
|
||||||
cmdidx += 2;
|
|
||||||
break;
|
|
||||||
case 'c': // cardid
|
|
||||||
cid = param_get32ex(Cmd, cmdidx + 1, 0, 10);
|
|
||||||
cmdidx += 2;
|
|
||||||
break;
|
|
||||||
case 'q': // q5
|
|
||||||
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
|
|
||||||
q5 = true;
|
|
||||||
cmdidx++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Skip unknown
|
|
||||||
cmdidx++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLIGetStrWithReturn(ctx, 2, keritype, &typeLen);
|
||||||
|
|
||||||
|
fc = arg_get_int_def(ctx, 3, 0);
|
||||||
|
cid = arg_get_int_def(ctx, 4, 0);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
// Setup card data/build internal id
|
// Setup card data/build internal id
|
||||||
switch (keritype) {
|
switch (keritype[0]) {
|
||||||
case 'i' : // Internal ID
|
case 'i' : // Internal ID
|
||||||
// MSB is ONE
|
// MSB is ONE
|
||||||
internalid = cid | 0x80000000;
|
internalid = cid | 0x80000000;
|
||||||
|
@ -283,6 +241,9 @@ static int CmdKeriClone(const char *Cmd) {
|
||||||
case 'm' : // MS
|
case 'm' : // MS
|
||||||
CmdKeriMSScramble(Scramble, &fc, &cid, &internalid);
|
CmdKeriMSScramble(Scramble, &fc, &cid, &internalid);
|
||||||
break;
|
break;
|
||||||
|
default :
|
||||||
|
PrintAndLogEx(ERR, "Invalid type");
|
||||||
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare and write to card
|
// Prepare and write to card
|
||||||
|
@ -303,11 +264,23 @@ static int CmdKeriClone(const char *Cmd) {
|
||||||
|
|
||||||
static int CmdKeriSim(const char *Cmd) {
|
static int CmdKeriSim(const char *Cmd) {
|
||||||
|
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
CLIParserContext *ctx;
|
||||||
if (strlen(Cmd) == 0 || cmdp == 'h')
|
CLIParserInit(&ctx, "lf keri sim",
|
||||||
return usage_lf_keri_sim();
|
"Enables simulation of KERI card with card number.",
|
||||||
|
"lf keri sim --id 112233"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_int1(NULL, "id", "<dec>", "KERI Internal ID"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
uint64_t internalid = arg_get_int_def(ctx, 1, 0);
|
||||||
|
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
uint64_t internalid = param_get32ex(Cmd, 0, 0, 10);
|
|
||||||
internalid |= 0x80000000;
|
internalid |= 0x80000000;
|
||||||
internalid <<= 3;
|
internalid <<= 3;
|
||||||
internalid += 7;
|
internalid += 7;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
|
#include "cliparser.h"
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
#include "pm3_cmd.h"
|
#include "pm3_cmd.h"
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
|
@ -24,172 +25,134 @@
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_wiegand_list(void) {
|
static void print_wiegand_code(wiegand_message_t *packed) {
|
||||||
PrintAndLogEx(NORMAL, "List available wiegand formats");
|
const char* s = "Encoded wiegand: ";
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_wiegand_encode(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Encode wiegand formatted number to raw hex");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: wiegand encode [w <format>] [<field> <value (decimal)>] {...}");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " w <format> see `wiegand list` for available formats");
|
|
||||||
PrintAndLogEx(NORMAL, " c <value> card number");
|
|
||||||
PrintAndLogEx(NORMAL, " f <value> facility code");
|
|
||||||
PrintAndLogEx(NORMAL, " i <value> issue Level");
|
|
||||||
PrintAndLogEx(NORMAL, " o <value> OEM code");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "samples:");
|
|
||||||
PrintAndLogEx(NORMAL, " wiegand encode w H10301 f 101 c 1337");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_wiegand_decode(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Decode raw hex to wiegand format");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: wiegand decode [id] <p>");
|
|
||||||
PrintAndLogEx(NORMAL, " p ignore invalid parity");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Samples:");
|
|
||||||
PrintAndLogEx(NORMAL, " wiegand decode 2006f623ae");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PrintTagId(wiegand_message_t *packed) {
|
|
||||||
if (packed->Top != 0) {
|
if (packed->Top != 0) {
|
||||||
PrintAndLogEx(SUCCESS, "Card ID: %X%08X%08X",
|
PrintAndLogEx(SUCCESS, "%s" _GREEN_("%X%08X%08X"),
|
||||||
(uint32_t)packed->Top,
|
s,
|
||||||
(uint32_t)packed->Mid,
|
(uint32_t)packed->Top,
|
||||||
(uint32_t)packed->Bot)
|
(uint32_t)packed->Mid,
|
||||||
;
|
(uint32_t)packed->Bot
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(SUCCESS, "Card ID: %X%08X",
|
PrintAndLogEx(SUCCESS, "%s" _YELLOW_("%X%08X"),
|
||||||
(uint32_t)packed->Mid,
|
s,
|
||||||
(uint32_t)packed->Bot)
|
(uint32_t)packed->Mid,
|
||||||
;
|
(uint32_t)packed->Bot
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdWiegandList(const char *Cmd) {
|
int CmdWiegandList(const char *Cmd) {
|
||||||
bool errors = false;
|
|
||||||
char cmdp = 0;
|
CLIParserContext *ctx;
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
CLIParserInit(&ctx, "wiegand info",
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
"List available wiegand formats",
|
||||||
case 'h':
|
"wiegand list"
|
||||||
return usage_wiegand_list();
|
);
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
void *argtable[] = {
|
||||||
errors = true;
|
arg_param_begin,
|
||||||
break;
|
arg_param_end
|
||||||
}
|
};
|
||||||
}
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
HIDListFormats();
|
HIDListFormats();
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdWiegandEncode(const char *Cmd) {
|
int CmdWiegandEncode(const char *Cmd) {
|
||||||
|
|
||||||
int format_idx = -1;
|
CLIParserContext *ctx;
|
||||||
char format[16] = {0};
|
CLIParserInit(&ctx, "wiegand encode",
|
||||||
|
"Encode wiegand formatted number to raw hex",
|
||||||
|
"wiegand encode -w H10301 --fc 101 --cn 1337"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_u64_0(NULL, "fc", "<dec>", "facility number"),
|
||||||
|
arg_u64_1(NULL, "cn", "<dec>", "card number"),
|
||||||
|
arg_u64_0(NULL, "issue", "<dec>", "issue level"),
|
||||||
|
arg_u64_0(NULL, "oem", "<dec>", "OEM code"),
|
||||||
|
arg_strx1("w", "wiegand", "<format>", "see `wiegand list` for available formats"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
wiegand_card_t data;
|
wiegand_card_t data;
|
||||||
memset(&data, 0, sizeof(wiegand_card_t));
|
memset(&data, 0, sizeof(wiegand_card_t));
|
||||||
|
|
||||||
bool errors = false;
|
data.FacilityCode = arg_get_u32_def(ctx, 1, 0);
|
||||||
char cmdp = 0;
|
data.CardNumber = arg_get_u64_def(ctx, 2, 0);
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
data.IssueLevel = arg_get_u32_def(ctx, 3, 0);
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
data.OEM = arg_get_u32_def(ctx, 4, 0);
|
||||||
case 'h':
|
|
||||||
return usage_wiegand_encode();
|
int len = 0;
|
||||||
case 'w':
|
char format[16] = {0};
|
||||||
param_getstr(Cmd, cmdp + 1, format, sizeof(format));
|
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t*)format, sizeof(format), &len);
|
||||||
format_idx = HIDFindCardFormat(format);
|
CLIParserFree(ctx);
|
||||||
if (format_idx == -1) {
|
|
||||||
PrintAndLogEx(WARNING, "Unknown format: %s", format);
|
int idx = HIDFindCardFormat(format);
|
||||||
errors = true;
|
if (idx == -1) {
|
||||||
}
|
PrintAndLogEx(WARNING, "Unknown format: %s", format);
|
||||||
cmdp += 2;
|
return PM3_EINVARG;
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
data.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
data.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
data.CardNumber = param_get64ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
data.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (errors || cmdp == 0) return usage_wiegand_encode();
|
|
||||||
|
|
||||||
wiegand_message_t packed;
|
wiegand_message_t packed;
|
||||||
memset(&packed, 0, sizeof(wiegand_message_t));
|
memset(&packed, 0, sizeof(wiegand_message_t));
|
||||||
|
|
||||||
if (HIDPack(format_idx, &data, &packed) == false) {
|
if (HIDPack(idx, &data, &packed) == false) {
|
||||||
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
|
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintTagId(&packed);
|
print_wiegand_code(&packed);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdWiegandDecode(const char *Cmd) {
|
int CmdWiegandDecode(const char *Cmd) {
|
||||||
|
|
||||||
uint32_t top = 0, mid = 0, bot = 0;
|
CLIParserContext *ctx;
|
||||||
bool ignore_parity = false, gothex = false;
|
CLIParserInit(&ctx, "wiegand decode",
|
||||||
bool errors = false;
|
"Decode raw hex to wiegand format",
|
||||||
char cmdp = 0;
|
"wiegand decode --raw 2006f623ae"
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
);
|
||||||
uint32_t slen = param_getlength(Cmd, cmdp);
|
|
||||||
slen++; // null termin
|
|
||||||
if (slen > 2) {
|
|
||||||
char *s = calloc(slen, sizeof(uint8_t));
|
|
||||||
param_getstr(Cmd, cmdp, s, slen);
|
|
||||||
hexstring_to_u96(&top, &mid, &bot, s);
|
|
||||||
free(s);
|
|
||||||
gothex = true;
|
|
||||||
cmdp++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
|
||||||
case 'h':
|
|
||||||
return usage_wiegand_decode();
|
|
||||||
case 'p':
|
|
||||||
ignore_parity = true;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (gothex == false)
|
|
||||||
errors = true;
|
|
||||||
|
|
||||||
if (errors || cmdp < 1) return usage_wiegand_decode();
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_lit0("p", "parity", "ignore invalid parity"),
|
||||||
|
arg_strx1(NULL, "raw", "<hex>", "raw hex to be decoded"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
bool ignore_parity = arg_get_lit(ctx, 1);
|
||||||
|
int len = 0;
|
||||||
|
char hex[40] = {0};
|
||||||
|
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t*)hex, sizeof(hex), &len);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
PrintAndLogEx(ERR, "empty input");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t top = 0, mid = 0, bot = 0;
|
||||||
|
hexstring_to_u96(&top, &mid, &bot, hex);
|
||||||
|
|
||||||
wiegand_message_t packed = initialize_message_object(top, mid, bot);
|
wiegand_message_t packed = initialize_message_object(top, mid, bot);
|
||||||
|
|
||||||
HIDTryUnpack(&packed, ignore_parity);
|
HIDTryUnpack(&packed, ignore_parity);
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"list", CmdWiegandList, AlwaysAvailable, "List available wiegand formats"},
|
{"list", CmdWiegandList, AlwaysAvailable, "List available wiegand formats"},
|
||||||
{"encode", CmdWiegandEncode, AlwaysAvailable, "Convert "},
|
{"encode", CmdWiegandEncode, AlwaysAvailable, "Encode to wiegand raw hex"},
|
||||||
{"decode", CmdWiegandDecode, AlwaysAvailable, "Convert raw hex to wiegand format"},
|
{"decode", CmdWiegandDecode, AlwaysAvailable, "Convert raw hex to decoded wiegand format"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ void InitGraphics(int argc, char **argv, char *script_cmds_file, char *script_cm
|
||||||
void ExitGraphics(void);
|
void ExitGraphics(void);
|
||||||
|
|
||||||
extern double CursorScaleFactor;
|
extern double CursorScaleFactor;
|
||||||
|
extern char CursorScaleFactorUnit[11];
|
||||||
extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, GridOffset;
|
extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, GridOffset;
|
||||||
extern uint32_t CursorCPos, CursorDPos;
|
extern uint32_t CursorCPos, CursorDPos;
|
||||||
extern int CommandFinished;
|
extern int CommandFinished;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// GUI (QT)
|
// GUI (QT)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "proxguiqt.h"
|
#include "proxguiqt.h"
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
|
@ -424,7 +424,8 @@ void Plot::PlotGraph(int *buffer, size_t len, QRect plotRect, QRect annotationRe
|
||||||
if (len == 0) return;
|
if (len == 0) return;
|
||||||
// clock_t begin = clock();
|
// clock_t begin = clock();
|
||||||
QPainterPath penPath;
|
QPainterPath penPath;
|
||||||
int vMin = INT_MAX, vMax = INT_MIN, vMean = 0, v = 0;
|
int vMin = INT_MAX, vMax = INT_MIN, v = 0;
|
||||||
|
int64_t vMean = 0;
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
int x = xCoordOf(GraphStart, plotRect);
|
int x = xCoordOf(GraphStart, plotRect);
|
||||||
int y = yCoordOf(buffer[GraphStart], plotRect, g_absVMax);
|
int y = yCoordOf(buffer[GraphStart], plotRect, g_absVMax);
|
||||||
|
@ -447,7 +448,8 @@ void Plot::PlotGraph(int *buffer, size_t len, QRect plotRect, QRect annotationRe
|
||||||
if (v > vMax) vMax = v;
|
if (v > vMax) vMax = v;
|
||||||
vMean += v;
|
vMean += v;
|
||||||
}
|
}
|
||||||
vMean /= (i - GraphStart);
|
GraphStop = i;
|
||||||
|
vMean /= (GraphStop - GraphStart);
|
||||||
|
|
||||||
painter->setPen(getColor(graphNum));
|
painter->setPen(getColor(graphNum));
|
||||||
|
|
||||||
|
@ -483,10 +485,9 @@ void Plot::PlotGraph(int *buffer, size_t len, QRect plotRect, QRect annotationRe
|
||||||
//Graph annotations
|
//Graph annotations
|
||||||
painter->drawPath(penPath);
|
painter->drawPath(penPath);
|
||||||
char str[200];
|
char str[200];
|
||||||
sprintf(str, "max=%d min=%d mean=%d n=%u/%zu CursorAVal=[%d] CursorBVal=[%d]",
|
sprintf(str, "max=%d min=%d mean=%" PRId64 " n=%u/%zu CursorAVal=[%d] CursorBVal=[%d]",
|
||||||
vMax, vMin, vMean, i, len, buffer[CursorAPos], buffer[CursorBPos]);
|
vMax, vMin, vMean, GraphStop - GraphStart, len, buffer[CursorAPos], buffer[CursorBPos]);
|
||||||
painter->drawText(20, annotationRect.bottom() - 23 - 20 * graphNum, str);
|
painter->drawText(20, annotationRect.bottom() - 23 - 20 * graphNum, str);
|
||||||
|
|
||||||
//clock_t end = clock();
|
//clock_t end = clock();
|
||||||
//double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
//double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||||
//printf("Plot time %f\n", elapsed_secs);
|
//printf("Plot time %f\n", elapsed_secs);
|
||||||
|
@ -596,10 +597,19 @@ void Plot::paintEvent(QPaintEvent *event) {
|
||||||
|
|
||||||
//Draw annotations
|
//Draw annotations
|
||||||
char str[200];
|
char str[200];
|
||||||
sprintf(str, "@%u dt=%u [%2.2f] zoom=%2.2f CursorAPos=%u CursorBPos=%u GridX=%d GridY=%d (%s) GridXoffset=%d",
|
char scalestr[30] = {0};
|
||||||
|
if (CursorScaleFactor != 1) {
|
||||||
|
if (CursorScaleFactorUnit[0] == '\x00') {
|
||||||
|
sprintf(scalestr, "[%2.2f] ", ((int32_t)(CursorBPos - CursorAPos)) / CursorScaleFactor);
|
||||||
|
} else {
|
||||||
|
sprintf(scalestr, "[%2.2f %s] ", ((int32_t)(CursorBPos - CursorAPos)) / CursorScaleFactor, CursorScaleFactorUnit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf(str, "@%u..%u dt=%i %szoom=%2.2f CursorAPos=%u CursorBPos=%u GridX=%d GridY=%d (%s) GridXoffset=%d",
|
||||||
GraphStart,
|
GraphStart,
|
||||||
|
GraphStop,
|
||||||
CursorBPos - CursorAPos,
|
CursorBPos - CursorAPos,
|
||||||
((int32_t)(CursorBPos - CursorAPos)) / CursorScaleFactor,
|
scalestr,
|
||||||
GraphPixelsPerPoint,
|
GraphPixelsPerPoint,
|
||||||
CursorAPos,
|
CursorAPos,
|
||||||
CursorBPos,
|
CursorBPos,
|
||||||
|
@ -637,7 +647,7 @@ void Plot::closeEvent(QCloseEvent *event) {
|
||||||
g_useOverlays = false;
|
g_useOverlays = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plot::Zoom(float factor, int refX) {
|
void Plot::Zoom(double factor, int refX) {
|
||||||
if (factor >= 1) { // Zoom in
|
if (factor >= 1) { // Zoom in
|
||||||
if (GraphPixelsPerPoint <= 25 * factor) {
|
if (GraphPixelsPerPoint <= 25 * factor) {
|
||||||
GraphPixelsPerPoint *= factor;
|
GraphPixelsPerPoint *= factor;
|
||||||
|
@ -677,14 +687,38 @@ void Plot::Move(int offset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plot::Trim(void) {
|
||||||
|
uint32_t lref, rref;
|
||||||
|
const double zoom_offset = 1.148698354997035; // 2**(1/5)
|
||||||
|
if ((CursorAPos == 0) || (CursorBPos == 0)) { // if we don't have both cursors set
|
||||||
|
lref = GraphStart;
|
||||||
|
rref = GraphStop;
|
||||||
|
} else {
|
||||||
|
lref = CursorAPos < CursorBPos ? CursorAPos : CursorBPos;
|
||||||
|
rref = CursorAPos < CursorBPos ? CursorBPos : CursorAPos;
|
||||||
|
// GraphPixelsPerPoint mush remain a power of zoom_offset
|
||||||
|
double GPPPtarget = GraphPixelsPerPoint * (GraphStop - GraphStart) / (rref - lref);
|
||||||
|
while (GraphPixelsPerPoint < GPPPtarget) {
|
||||||
|
GraphPixelsPerPoint *= zoom_offset;
|
||||||
|
}
|
||||||
|
GraphPixelsPerPoint /= zoom_offset;
|
||||||
|
CursorAPos -= lref;
|
||||||
|
CursorBPos -= lref;
|
||||||
|
}
|
||||||
|
for (uint32_t i = lref; i < rref; ++i)
|
||||||
|
GraphBuffer[i - lref] = GraphBuffer[i];
|
||||||
|
GraphTraceLen = rref - lref;
|
||||||
|
GraphStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Plot::wheelEvent(QWheelEvent *event) {
|
void Plot::wheelEvent(QWheelEvent *event) {
|
||||||
// event->delta()
|
// event->delta()
|
||||||
// 120 => shift right 5%
|
// 120 => shift right 5%
|
||||||
// -120 => shift left 5%
|
// -120 => shift left 5%
|
||||||
const float move_offset = 0.05;
|
const float move_offset = 0.05;
|
||||||
// -120+shift => zoom in 10%
|
// -120+shift => zoom in (5 times = *2)
|
||||||
// 120+shift => zoom out 10%
|
// 120+shift => zoom out (5 times = /2)
|
||||||
const float zoom_offset = 0.1;
|
const double zoom_offset = 1.148698354997035; // 2**(1/5)
|
||||||
if (event->modifiers() & Qt::ShiftModifier) {
|
if (event->modifiers() & Qt::ShiftModifier) {
|
||||||
// event->position doesn't exist in QT5.12.8, both exist in 5.14.2 and event->x doesn't exist in 5.15.0
|
// event->position doesn't exist in QT5.12.8, both exist in 5.14.2 and event->x doesn't exist in 5.15.0
|
||||||
#if QT_VERSION >= 0x050d00
|
#if QT_VERSION >= 0x050d00
|
||||||
|
@ -697,10 +731,15 @@ void Plot::wheelEvent(QWheelEvent *event) {
|
||||||
x += GraphStart;
|
x += GraphStart;
|
||||||
// event->angleDelta doesn't exist in QT4, both exist in 5.12.8 and 5.14.2 and event->delta doesn't exist in 5.15.0
|
// event->angleDelta doesn't exist in QT4, both exist in 5.12.8 and 5.14.2 and event->delta doesn't exist in 5.15.0
|
||||||
#if QT_VERSION >= 0x050d00
|
#if QT_VERSION >= 0x050d00
|
||||||
Zoom(1.0 - (float)event->angleDelta().y() / (120 / zoom_offset), x);
|
float delta = event->angleDelta().y();
|
||||||
#else
|
#else
|
||||||
Zoom(1.0 - (float)event->delta() / (120 / zoom_offset), x);
|
float delta = event->delta();
|
||||||
#endif
|
#endif
|
||||||
|
if (delta < 0) {
|
||||||
|
Zoom(zoom_offset, x);
|
||||||
|
} else {
|
||||||
|
Zoom(1.0 / zoom_offset, x);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
#if QT_VERSION >= 0x050d00
|
#if QT_VERSION >= 0x050d00
|
||||||
Move(PageWidth * (-(float)event->angleDelta().y() / (120 / move_offset)));
|
Move(PageWidth * (-(float)event->angleDelta().y() / (120 / move_offset)));
|
||||||
|
@ -794,6 +833,7 @@ void Plot::keyPressEvent(QKeyEvent *event) {
|
||||||
puts("\tH Show help");
|
puts("\tH Show help");
|
||||||
puts("\tL Toggle lock grid relative to samples");
|
puts("\tL Toggle lock grid relative to samples");
|
||||||
puts("\tQ Hide window");
|
puts("\tQ Hide window");
|
||||||
|
puts("\tT Trim data on displayed window or on cursors if defined");
|
||||||
puts("\tHOME Move to the start of the graph");
|
puts("\tHOME Move to the start of the graph");
|
||||||
puts("\tEND Move to the end of the graph");
|
puts("\tEND Move to the end of the graph");
|
||||||
puts("\tPGUP Page left");
|
puts("\tPGUP Page left");
|
||||||
|
@ -823,6 +863,10 @@ void Plot::keyPressEvent(QKeyEvent *event) {
|
||||||
master->hide();
|
master->hide();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_T:
|
||||||
|
Trim();
|
||||||
|
break;
|
||||||
|
|
||||||
case Qt::Key_Home:
|
case Qt::Key_Home:
|
||||||
GraphStart = 0;
|
GraphStart = 0;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -32,6 +32,7 @@ class Plot: public QWidget {
|
||||||
private:
|
private:
|
||||||
QWidget *master;
|
QWidget *master;
|
||||||
uint32_t GraphStart; // Starting point/offset for the left side of the graph
|
uint32_t GraphStart; // Starting point/offset for the left side of the graph
|
||||||
|
uint32_t GraphStop; // Stop point/offset for the right side of the graph
|
||||||
double GraphPixelsPerPoint; // How many visual pixels are between each sample point (x axis)
|
double GraphPixelsPerPoint; // How many visual pixels are between each sample point (x axis)
|
||||||
uint32_t CursorAPos;
|
uint32_t CursorAPos;
|
||||||
uint32_t CursorBPos;
|
uint32_t CursorBPos;
|
||||||
|
@ -50,8 +51,9 @@ class Plot: public QWidget {
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *event);
|
void paintEvent(QPaintEvent *event);
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
void Zoom(float factor, int refX);
|
void Zoom(double factor, int refX);
|
||||||
void Move(int offset);
|
void Move(int offset);
|
||||||
|
void Trim(void);
|
||||||
void wheelEvent(QWheelEvent *event);
|
void wheelEvent(QWheelEvent *event);
|
||||||
void mouseMoveEvent(QMouseEvent *event);
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
void mousePressEvent(QMouseEvent *event) { mouseMoveEvent(event); }
|
void mousePressEvent(QMouseEvent *event) { mouseMoveEvent(event); }
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
session_arg_t session;
|
session_arg_t session;
|
||||||
|
|
||||||
double CursorScaleFactor = 1;
|
double CursorScaleFactor = 1;
|
||||||
|
char CursorScaleFactorUnit[11] = {0};
|
||||||
int PlotGridX = 0, PlotGridY = 0, PlotGridXdefault = 64, PlotGridYdefault = 64;
|
int PlotGridX = 0, PlotGridY = 0, PlotGridXdefault = 64, PlotGridYdefault = 64;
|
||||||
uint32_t CursorCPos = 0, CursorDPos = 0;
|
uint32_t CursorCPos = 0, CursorDPos = 0;
|
||||||
double GraphPixelsPerPoint = 1.f; // How many visual pixels are between each sample point (x axis)
|
double GraphPixelsPerPoint = 1.f; // How many visual pixels are between each sample point (x axis)
|
||||||
|
|
|
@ -332,23 +332,25 @@ Convert Site & Facility code to Wiegand raw hex
|
||||||
```
|
```
|
||||||
Options
|
Options
|
||||||
---
|
---
|
||||||
w <format> o <OEM> f <FC> c <CN> i <issuelevel>
|
-w <format> --oem <OEM> --fc <FC> --cn <CN> --issue <issuelevel>
|
||||||
w : wiegand format to use
|
|
||||||
o : OEM number / site code
|
|
||||||
f : facility code
|
|
||||||
c : card number
|
|
||||||
i : issue level
|
|
||||||
|
|
||||||
pm3 --> wiegand encode 0 56 150
|
-w : wiegand format to use
|
||||||
|
--oem : OEM number / site code
|
||||||
|
--fc : facility code
|
||||||
|
--cn : card number
|
||||||
|
--issue : issue level
|
||||||
|
|
||||||
|
pm3 --> wiegand encode -w H10301 --oem 0 --fc 56 --cn 150
|
||||||
```
|
```
|
||||||
|
|
||||||
Convert Site & Facility code from Wiegand raw hex to numbers
|
Convert Site & Facility code from Wiegand raw hex to numbers
|
||||||
```
|
```
|
||||||
Options
|
Options
|
||||||
---
|
---
|
||||||
p : ignore parity errors
|
-p : ignore parity errors
|
||||||
|
--raw : raw hex to be decoded
|
||||||
|
|
||||||
pm3 --> wiegand decode 2006f623ae
|
pm3 --> wiegand decode --raw 2006f623ae
|
||||||
```
|
```
|
||||||
|
|
||||||
## HID Prox
|
## HID Prox
|
||||||
|
@ -379,14 +381,18 @@ Brute force HID reader
|
||||||
```
|
```
|
||||||
Options
|
Options
|
||||||
---
|
---
|
||||||
a <format> : 26|33|34|35|37|40|44|84
|
-v, --verbose : verbose logging, show all tries
|
||||||
f <facility-code> : 8-bit value HID facility code
|
-w, --wiegand format : see `wiegand list` for available formats
|
||||||
c <cardnumber> : (optional) cardnumber to start with, max 65535
|
-f, --fn dec : facility code
|
||||||
d <delay> : delay betweens attempts in ms. Default 1000ms
|
-c, --cn dec : card number to start with
|
||||||
v : verbose logging, show all tries
|
-i dec : issue level
|
||||||
|
-o, --oem dec : OEM code
|
||||||
|
-d, --delay dec : delay betweens attempts in ms. Default 1000ms
|
||||||
|
--up : direction to increment card number. (default is both directions)
|
||||||
|
--down : direction to decrement card number. (default is both directions)
|
||||||
|
|
||||||
pm3 --> lf hid brute a 26 f 224
|
pm3 --> lf hid brute -w H10301 -f 224
|
||||||
pm3 --> lf hid brute v a 26 f 21 c 200 d 2000
|
pm3 --> lf hid brute -v -w H10301 -f 21 -c 200 -d 2000
|
||||||
```
|
```
|
||||||
|
|
||||||
## Indala
|
## Indala
|
||||||
|
@ -552,7 +558,7 @@ pm3 --> script list
|
||||||
View lua helptext
|
View lua helptext
|
||||||
|
|
||||||
```
|
```
|
||||||
pm3 --> script run <nameofscript> -h
|
pm3 --> script run <nameofscript> -h
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -595,15 +601,15 @@ Load default keys into flash memory (RDV4 only)
|
||||||
```
|
```
|
||||||
Options
|
Options
|
||||||
---
|
---
|
||||||
o <offset> : offset in memory
|
-o <offset> : offset in memory
|
||||||
f <filename> : file name
|
-f <filename> : file name
|
||||||
m : upload 6 bytes keys (mifare key dictionary)
|
--mfc : upload 6 bytes keys (mifare key dictionary)
|
||||||
i : upload 8 bytes keys (iClass key dictionary)
|
--iclass : upload 8 bytes keys (iClass key dictionary)
|
||||||
t : upload 4 bytes keys (pwd dictionary)
|
--t55xx : upload 4 bytes keys (pwd dictionary)
|
||||||
|
|
||||||
pm3 --> mem load f mfc_default_keys m
|
pm3 --> mem load -f mfc_default_keys --mfc
|
||||||
pm3 --> mem load f t55xx_default_pwds t
|
pm3 --> mem load -f t55xx_default_pwds --t5xx
|
||||||
pm3 --> mem load f iclass_default_keys i
|
pm3 --> mem load -f iclass_default_keys --iclass
|
||||||
```
|
```
|
||||||
|
|
||||||
## Sim Module
|
## Sim Module
|
||||||
|
|
|
@ -25,14 +25,14 @@ And then it fell into silence since it wasn't well documented how to use the cli
|
||||||
Fast forward today, where more commands has used the cliparser but it still wasn't the natural way when adding a new client command to the Proxmark3 client.
|
Fast forward today, where more commands has used the cliparser but it still wasn't the natural way when adding a new client command to the Proxmark3 client.
|
||||||
After more discussions among @doegox, @iceman1001 and @mrwalker the concept became more clear on how to use the cliparser lib in the _preferred_ way.
|
After more discussions among @doegox, @iceman1001 and @mrwalker the concept became more clear on how to use the cliparser lib in the _preferred_ way.
|
||||||
|
|
||||||
The aftermath was a design and layout specfied which lead to a simpler implemtentation of the cliparser in the client source code while still unfiy all helptexts with the new colours support and a defined layout. As seen below, the simplicity and clearness.
|
The aftermath was a design and layout specified which lead to a simpler implementation of the cliparser in the client source code while still unifiy all helptexts with the new colours support and a defined layout. As seen below, the simplicity and clearness.
|
||||||
|
|
||||||
![sample of new style helptext](http://www.icedev.se/proxmark3/helptext.png)
|
![sample of new style helptext](http://www.icedev.se/proxmark3/helptext.png)
|
||||||
|
|
||||||
|
|
||||||
Furthermore @mrwalker offered to take notes and thus this document was created.
|
Furthermore @mrwalker offered to take notes and thus this document was created.
|
||||||
|
|
||||||
This is the _new_ and _prefered_ way to implement _helptext_ and _cli parsing_ for Proxmark3 client commands and it's external tools.
|
This is the _new_ and _preferred_ way to implement _helptext_ and _cli parsing_ for Proxmark3 client commands and it's external tools.
|
||||||
|
|
||||||
|
|
||||||
## cliparser setup and use
|
## cliparser setup and use
|
||||||
|
@ -45,7 +45,7 @@ It will also add the `-h --help` option automatic.
|
||||||
* where possible all options should be lowercase.
|
* where possible all options should be lowercase.
|
||||||
* extended options preceded with -- should be short
|
* extended options preceded with -- should be short
|
||||||
* options provided directly (without an option identifier) should be avoided.
|
* options provided directly (without an option identifier) should be avoided.
|
||||||
* -vv for extra verbos should be avoided; use of debug level is preferred.
|
* -vv for extra verbose should be avoided; use of debug level is preferred.
|
||||||
* with --options the equal is not needed (will work with and without) so don't use '='
|
* with --options the equal is not needed (will work with and without) so don't use '='
|
||||||
e.g. cmd --cn 12345
|
e.g. cmd --cn 12345
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ It will also add the `-h --help` option automatic.
|
||||||
--raw : raw data
|
--raw : raw data
|
||||||
-k --key : key supplied
|
-k --key : key supplied
|
||||||
-n --keyno : key number to use
|
-n --keyno : key number to use
|
||||||
-v --verbose : flag when output should provide more information, not conidered debug.
|
-v --verbose : flag when output should provide more information, not considered debug.
|
||||||
-1 --buffer : use the sample buffer
|
-1 --buffer : use the sample buffer
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ In the command function, setup the context
|
||||||
|
|
||||||
|
|
||||||
### define the context
|
### define the context
|
||||||
CLIParserInit (\<context\>, \<description\>, \<notes\n examples ... \>);
|
`CLIParserInit (\<context\>, \<description\>, \<notes\n examples ... \>);`
|
||||||
|
|
||||||
use -> to separate example and example comment and \\n to separate examples.
|
use -> to separate example and example comment and \\n to separate examples.
|
||||||
e.g. lf indala clone -r a0000000a0002021 -> this uses .....
|
e.g. lf indala clone -r a0000000a0002021 -> this uses .....
|
||||||
|
@ -103,43 +103,59 @@ e.g. lf indala clone -r a0000000a0002021 -> this uses .....
|
||||||
};
|
};
|
||||||
|
|
||||||
_All options has a parameter index, since `-h --help` is added automatic, it will be assigned index 0.
|
_All options has a parameter index, since `-h --help` is added automatic, it will be assigned index 0.
|
||||||
Hence all options you add will start at index 1 and upwards._
|
Hence all options you add will start at index 1 and upwards. It added in the define "arg_param_begin_
|
||||||
|
|
||||||
**Notes:**
|
### Notes:
|
||||||
**bool option. true if supplied**
|
#### bool option. true if supplied
|
||||||
bool : arg_lit0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
`bool : arg_lit0 ("<short option>", "<long option>", <"description">)`
|
||||||
|
|
||||||
**integer that is optional**
|
#### integer that is optional
|
||||||
optional integer : arg_int0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
`optional integer : arg_int0 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||||
|
|
||||||
**integer that is required**
|
#### integer that is required
|
||||||
required integer : arg_int1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
`required integer : arg_int1 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||||
|
|
||||||
**String option that is optional and only one instance can be provided**
|
#### double that is optional
|
||||||
optional string : arg_str0("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
`optional double : arg_dbl0 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||||
|
|
||||||
**String option that is required and only one instance can be provided**
|
#### double that is required
|
||||||
required string : arg_str1("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
`required double : arg_dbl1 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||||
|
|
||||||
**String option that is optional and can have up to 250 instances provided**
|
#### String option that is optional and only one instance can be provided
|
||||||
optional string : arg_strx0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
`optional string : arg_str0 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||||
|
|
||||||
|
#### String option that is required and only one instance can be provided
|
||||||
|
`required string : arg_str1 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||||
|
|
||||||
|
#### String option that is optional and can have up to 250 instances provided
|
||||||
|
`optional string : arg_strx0 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||||
|
|
||||||
|
#### String option that is required/at least one instance and can have up to 250 instances
|
||||||
|
`required string : arg_strx1 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||||
|
|
||||||
|
Unsigned values, like u32 and u64 can be accomplished with
|
||||||
|
|
||||||
|
#### unsigned integer optional
|
||||||
|
`optional unsigned : arg_u64_0 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||||
|
|
||||||
|
#### unsigned integer required
|
||||||
|
`required unsigned : arg_u64_1 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||||
|
|
||||||
**String option that is required/at least one instance and can have up to 250 instances**
|
|
||||||
required string : arg_strx1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
|
||||||
|
|
||||||
**if an option does not have a short or long option, use NULL in its place**
|
**if an option does not have a short or long option, use NULL in its place**
|
||||||
|
|
||||||
|
|
||||||
### show the menu
|
### show the menu
|
||||||
CLIExecWithReturn(\<context\>, \<command line to parse\>, \<arg/opt table\>, \<return on error\>);
|
`CLIExecWithReturn(\<context\>, \<command line to parse\>, \<arg/opt table\>, \<return on error\>);`
|
||||||
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
### clean up
|
### clean up
|
||||||
Once you have extracted the options, cleanup the context.
|
Once you have extracted the options, cleanup the context.
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
### retreiving options
|
### retrieving options
|
||||||
|
|
||||||
|
|
||||||
The parser will format and color and layout as needed.
|
The parser will format and color and layout as needed.
|
||||||
|
@ -156,6 +172,18 @@ arg_get_int_def(\<context\>, \<opt index\>, \<default value\>);
|
||||||
|
|
||||||
cardnumber = arg_get_int_def(ctx, 2, -1);
|
cardnumber = arg_get_int_def(ctx, 2, -1);
|
||||||
|
|
||||||
|
|
||||||
|
**uint32**
|
||||||
|
arg_get_u32_def(\<context\>, \<opt index\>, \<default value\>);
|
||||||
|
|
||||||
|
cardnumber = arg_get_u32_def(ctx, 2, 0);
|
||||||
|
|
||||||
|
**uint64**
|
||||||
|
arg_get_u64_def(\<context\>, \<opt index\>, \<default value\>);
|
||||||
|
|
||||||
|
cardnumber = arg_get_u64_def(ctx, 2, 0);
|
||||||
|
|
||||||
|
|
||||||
**hex option**
|
**hex option**
|
||||||
CLIGetHexWithReturn(\<context\>, \<opt index\>, \<store variable\>, \<ptr to stored length\>);
|
CLIGetHexWithReturn(\<context\>, \<opt index\>, \<store variable\>, \<ptr to stored length\>);
|
||||||
?? as an array of uint_8 ??
|
?? as an array of uint_8 ??
|
||||||
|
|
|
@ -38,6 +38,7 @@ typedef enum ISO14B_COMMAND {
|
||||||
ISO14B_SET_TIMEOUT = (1 << 8),
|
ISO14B_SET_TIMEOUT = (1 << 8),
|
||||||
ISO14B_SEND_CHAINING = (1 << 9),
|
ISO14B_SEND_CHAINING = (1 << 9),
|
||||||
ISO14B_SELECT_CTS = (1 << 10),
|
ISO14B_SELECT_CTS = (1 << 10),
|
||||||
|
ISO14B_CLEARTRACE = (1 << 11),
|
||||||
} iso14b_command_t;
|
} iso14b_command_t;
|
||||||
|
|
||||||
#endif // _ISO14B_H_
|
#endif // _ISO14B_H_
|
|
@ -32,7 +32,7 @@ lf hid clone 2006ec0c86
|
||||||
lf read s 10000
|
lf read s 10000
|
||||||
data save f lf_t5577_hid
|
data save f lf_t5577_hid
|
||||||
|
|
||||||
lf hid clone l 2006ec0c86
|
lf hid clone -l 2006ec0c86
|
||||||
lf read s 20000
|
lf read s 20000
|
||||||
data save f lf_t5577_hid_84
|
data save f lf_t5577_hid_84
|
||||||
|
|
||||||
|
@ -56,15 +56,15 @@ lf jablotron clone 112233
|
||||||
lf read s 16000
|
lf read s 16000
|
||||||
data save f lf_t5577_jablotron
|
data save f lf_t5577_jablotron
|
||||||
|
|
||||||
lf keri clone 112233
|
lf keri clone --id 112233
|
||||||
lf read s 10000
|
lf read s 10000
|
||||||
data save f lf_t5577_keri
|
data save f lf_t5577_keri
|
||||||
|
|
||||||
lf keri clone t i fc 6 cn 12345
|
lf keri clone -t i --fc 6 --id 12345
|
||||||
lf read s 10000
|
lf read s 10000
|
||||||
data save f lf_t5577_keri_internalid
|
data save f lf_t5577_keri_internalid
|
||||||
|
|
||||||
lf keri clone t m f 6 c 12345
|
lf keri clone -t m --fc 6 --id 12345
|
||||||
lf read s 10000
|
lf read s 10000
|
||||||
data save f lf_t5577_keri_msid
|
data save f lf_t5577_keri_msid
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue