mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-25 17:56:13 +08:00
commit
ce61d78425
204
appveyor.yml
204
appveyor.yml
|
@ -1,13 +1,17 @@
|
|||
version: 3.0.1.{build}
|
||||
image: Visual Studio 2019
|
||||
clone_folder: C:\ProxSpace\pm3\proxmark
|
||||
cache:
|
||||
- C:\cache -> appveyor.yml
|
||||
environment:
|
||||
proxspace_url: https://github.com/Gator96100/ProxSpace/archive/master.zip
|
||||
proxspace_zip_file: \proxspace.zip
|
||||
proxspace_zip_folder_name: ProxSpace-*
|
||||
proxspace_path: \ProxSpace
|
||||
proxspace_path: C:\ProxSpace
|
||||
proxspace_home_path: \ProxSpace\pm3
|
||||
proxspace_cache_path: C:\cache
|
||||
wsl_git_path: C:\proxmark
|
||||
APPVEYOR_SAVE_CACHE_ON_ERROR: true
|
||||
|
||||
init:
|
||||
- ps: >-
|
||||
|
@ -34,39 +38,19 @@ init:
|
|||
clone_script:
|
||||
- ps: >-
|
||||
|
||||
Function ExecUpdate($Text, $firstStart) {
|
||||
Write-Host "$Text"
|
||||
Start-Process "cmd.exe" "/c ""cd /D $env:proxspace_path && runme64.bat -c ""exit"""""
|
||||
$StartTime=[System.Environment]::TickCount
|
||||
Start-Sleep -s 10
|
||||
while($true) {
|
||||
$cmdprocess = Get-Process "cmd" -ErrorAction SilentlyContinue
|
||||
|
||||
if (!$cmdprocess -Or $cmdprocess.HasExited) {
|
||||
Write-Host "$Text" -NoNewLine
|
||||
Write-Host "[ OK ]" -ForegroundColor Green
|
||||
break
|
||||
}
|
||||
|
||||
if ($firstStart -And (Test-Path "$env:proxspace_path\msys2\etc\pacman.conf.pacnew")) {
|
||||
Start-Sleep -s 5
|
||||
$tmp = $cmdprocess.CloseMainWindow()
|
||||
Start-Sleep -s 5
|
||||
Stop-Process -Name "cmd" -Force -ErrorAction SilentlyContinue
|
||||
Write-Host "$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
|
||||
Function GitClone($Text, $Folder) {
|
||||
Write-Host "$Text" -NoNewLine
|
||||
if(-not $env:appveyor_pull_request_number) {
|
||||
git clone -q --branch=$env:appveyor_repo_branch https://github.com/$env:appveyor_repo_name.git $Folder
|
||||
cd $Folder
|
||||
git checkout -qf $env:appveyor_repo_commit
|
||||
} else {
|
||||
git clone -q https://github.com/$env:appveyor_repo_name.git $Folder
|
||||
cd $Folder
|
||||
git fetch -q origin +refs/pull/$env:appveyor_pull_request_number/merge:
|
||||
git checkout -qf FETCH_HEAD
|
||||
}
|
||||
Write-Host "[ OK ]" -ForegroundColor Green
|
||||
}
|
||||
|
||||
$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
|
||||
}
|
||||
|
||||
$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) {
|
||||
Write-Host "$Text" -NoNewLine
|
||||
if(-not $env:appveyor_pull_request_number) {
|
||||
|
@ -101,63 +173,18 @@ clone_script:
|
|||
Write-Host "[ OK ]" -ForegroundColor Green
|
||||
}
|
||||
|
||||
Write-Host "ProxSpace: Removing folder..." -NoNewLine
|
||||
Write-Host "ProxSpace: move cache..." -NoNewLine
|
||||
|
||||
$PSInstallTime=[System.Environment]::TickCount
|
||||
|
||||
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)
|
||||
Move-Item -Path "$env:proxspace_cache_path" -Destination "$env:proxspace_path\msys2\var\cache" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Host "[ OK ]" -ForegroundColor Gree
|
||||
|
||||
ExecUpdate "ProxSpace: initial msys2 startup..." $true
|
||||
|
||||
ExecUpdate "ProxSpace: installing required packages..." $false
|
||||
|
||||
|
||||
$psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "$env:proxspace_path\msys2\ps\09-proxspace_setup.post").Line.Split("""")[1]
|
||||
|
||||
Write-Host "ProxSpace version: $psversion" -ForegroundColor Yellow
|
||||
|
||||
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
|
||||
ExecUpdate "ProxSpace: installing required packages..." $false
|
||||
|
||||
Add-AppveyorMessage -Message "ProxSpace download and update took $(([System.Environment]::TickCount-$env:PSInstallTime) / 1000) sec" -Category Information
|
||||
|
||||
install:
|
||||
build_script:
|
||||
- ps: >-
|
||||
|
||||
|
@ -202,6 +229,9 @@ build_script:
|
|||
throw "Tests error."
|
||||
}
|
||||
}
|
||||
|
||||
#WSL: wait for installation to finish
|
||||
Receive-Job -Wait -Name WSLInstall
|
||||
|
||||
#Windows Subsystem for Linux (WSL)
|
||||
Write-Host "---------- WSL make ----------" -ForegroundColor Yellow
|
||||
|
@ -234,6 +264,16 @@ build_script:
|
|||
|
||||
#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
|
||||
|
||||
$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':
|
||||
return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
|
||||
case 'b':
|
||||
return iso14443b_apdu(apdu, length, false, response, respmaxlen);
|
||||
return iso14443b_apdu(apdu, length, false, response, respmaxlen, NULL);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len) {
|
|||
|
||||
optimizedSniff((uint16_t *)mem, *len);
|
||||
|
||||
if (DBGLEVEL >= DBG_INFO) {
|
||||
if (DBGLEVEL >= DBG_INFO) {
|
||||
Dbprintf("Trigger kicked in (%d >= 180)", r);
|
||||
Dbprintf("Collected %u samples", *len);
|
||||
}
|
||||
|
|
|
@ -2687,7 +2687,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
|||
LED_D_ON();
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode);
|
||||
SpinDelay(100);
|
||||
SpinDelay(50);
|
||||
|
||||
// Start the timer
|
||||
StartCountSspClk();
|
||||
|
|
|
@ -784,6 +784,7 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
|||
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
|
||||
((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
|
||||
Demod.sumI += ci;
|
||||
Demod.sumQ += cq;
|
||||
|
@ -1103,7 +1104,7 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
|
|||
|
||||
// Send SOF
|
||||
// 10-11 ETUs of ZERO
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < 11; i++) {
|
||||
tosend_stuffbit(0);
|
||||
}
|
||||
// 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
|
||||
// For PCD it ranges 0-57us === 0 - 6 ETU
|
||||
// FOR PICC it ranges 0-19us == 0 - 2 ETU
|
||||
|
||||
}
|
||||
|
||||
// Send EOF
|
||||
// 10-11 ETUs of ZERO
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < 11; i++) {
|
||||
tosend_stuffbit(0);
|
||||
}
|
||||
|
||||
tosend_stuffbit(1);
|
||||
/* Transition time. TR0 - guard time
|
||||
* TR0 - 8 ETU's minimum.
|
||||
* TR0 - 32 ETU's maximum for ATQB only
|
||||
* TR0 - FWT for all other commands
|
||||
* 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)
|
||||
tosend_stuffbit(1);
|
||||
|
@ -1168,7 +1167,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t
|
|||
/* Sends an APDU to the tag
|
||||
* 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];
|
||||
|
||||
|
@ -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);
|
||||
|
||||
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();
|
||||
|
||||
uint8_t *data_bytes = (uint8_t *) response;
|
||||
uint8_t *data_bytes = (uint8_t *) rxdata;
|
||||
|
||||
if (len <= 0) {
|
||||
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)
|
||||
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();
|
||||
|
||||
data_bytes = response;
|
||||
data_bytes = rxdata;
|
||||
// restore 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 (response)
|
||||
*response = data_bytes[0];
|
||||
if (res)
|
||||
*res = data_bytes[0];
|
||||
|
||||
// crc check
|
||||
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
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD);
|
||||
SpinDelay(100);
|
||||
SpinDelay(50);
|
||||
|
||||
// Start the timer
|
||||
StartCountSspClk();
|
||||
|
@ -1841,17 +1840,21 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
|||
|
||||
if ((param & ISO14B_CONNECT) == ISO14B_CONNECT) {
|
||||
iso14443b_setup();
|
||||
clear_trace();
|
||||
}
|
||||
|
||||
if ((param & ISO14B_SET_TIMEOUT))
|
||||
if ((param & ISO14B_SET_TIMEOUT) == ISO14B_SET_TIMEOUT) {
|
||||
iso14b_set_timeout(timeout);
|
||||
|
||||
}
|
||||
|
||||
if ((param & ISO14B_CLEARTRACE) == ISO14B_CLEARTRACE) {
|
||||
clear_trace();
|
||||
}
|
||||
set_tracing(true);
|
||||
|
||||
int status;
|
||||
uint32_t sendlen = sizeof(iso14b_card_select_t);
|
||||
iso14b_card_select_t card;
|
||||
memset((void*)&card, 0x00, sizeof(card));
|
||||
|
||||
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
|
||||
status = iso14443b_select_card(&card);
|
||||
|
@ -1877,9 +1880,10 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
|||
}
|
||||
|
||||
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);
|
||||
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) {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#endif
|
||||
|
||||
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_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) {
|
||||
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
||||
}
|
||||
FpgaDisableTracing();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1494,6 +1495,7 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui
|
|||
if (recv != NULL) {
|
||||
res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time);
|
||||
}
|
||||
FpgaDisableTracing();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env -S pm3 -s
|
||||
|
||||
mem load f mfc_default_keys m
|
||||
mem load f t55xx_default_pwds t
|
||||
mem load f iclass_default_keys i
|
||||
mem load -f mfc_default_keys --mfc
|
||||
mem load -f t55xx_default_pwds --t55xx
|
||||
mem load -f iclass_default_keys --iclass
|
||||
lf t55xx deviceconfig z p
|
||||
|
|
|
@ -14,7 +14,7 @@ lf search
|
|||
|
||||
rem Test of keri clone & read
|
||||
lf t55xx wipe
|
||||
lf keri clone 1337
|
||||
lf keri clone --id 1337
|
||||
lf keri read
|
||||
lf search
|
||||
|
||||
|
|
|
@ -1927,10 +1927,8 @@ struct arg_file *arg_filen(
|
|||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "argtable3.h"
|
||||
|
||||
|
||||
static void arg_int_resetfn(struct arg_int *parent) {
|
||||
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
|
||||
parent->count = 0;
|
||||
|
@ -2226,6 +2224,263 @@ struct arg_int *arg_intn(
|
|||
ARG_TRACE(("arg_intn() returns %p\n", 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.
|
||||
*
|
||||
|
@ -4020,7 +4275,10 @@ static void arg_parse_untagged(int argc,
|
|||
/* register an error for each unused argv[] entry */
|
||||
while (optind < argc) {
|
||||
/*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;
|
||||
|
@ -4195,7 +4453,8 @@ static void arg_cat_option(char *dest,
|
|||
#endif
|
||||
|
||||
if (datatype) {
|
||||
arg_cat(&dest, "=", &ndest);
|
||||
// arg_cat(&dest, "=", &ndest);
|
||||
arg_cat(&dest, " ", &ndest);
|
||||
if (optvalue) {
|
||||
arg_cat(&dest, "[", &ndest);
|
||||
arg_cat(&dest, datatype, &ndest);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include <stdio.h> /* FILE */
|
||||
#include <time.h> /* struct tm */
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -110,6 +111,12 @@ struct arg_int {
|
|||
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_hdr hdr; /* The mandatory argtable header struct */
|
||||
int count; /* Number of matching command line args */
|
||||
|
@ -176,32 +183,29 @@ struct arg_lit *arg_litn(const char *shortopts,
|
|||
int maxcount,
|
||||
const char *glossary);
|
||||
|
||||
struct arg_key *arg_key0(const char *keyword,
|
||||
int flags,
|
||||
struct arg_key *arg_key0(const char *keyword, int flags, const char *glossary);
|
||||
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);
|
||||
struct arg_key *arg_key1(const char *keyword,
|
||||
int flags,
|
||||
struct arg_u64 *arg_u64_1(const char *shortopts,
|
||||
const char *longopts,
|
||||
const char *datatype,
|
||||
const char *glossary);
|
||||
struct arg_key *arg_keyn(const char *keyword,
|
||||
int flags,
|
||||
struct arg_u64 *arg_u64_n(const char *shortopts,
|
||||
const char *longopts,
|
||||
const char *datatype,
|
||||
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_dbl *arg_dbl0(const char *shortopts,
|
||||
const char *longopts,
|
||||
|
|
|
@ -251,12 +251,13 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
|||
if (!ibuf)
|
||||
return 0;
|
||||
|
||||
if (ibuf > maxdatalen) {
|
||||
if (ibuf + 1 > maxdatalen) {
|
||||
printf("Parameter error: string too long, expect max %i chars\n", maxdatalen - 1);
|
||||
fflush(stdout);
|
||||
return 2;
|
||||
}
|
||||
|
||||
memcpy(data, tmp_buf, ibuf);
|
||||
memcpy(data, tmp_buf, ibuf + 1);
|
||||
*datalen = ibuf;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,22 +17,39 @@
|
|||
#define arg_param_begin arg_lit0("h", "help", "This help")
|
||||
#define arg_param_end arg_end(20)
|
||||
|
||||
#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_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_def(ctx, n, def)(arg_get_int_count((ctx), n) ? (arg_get_int((ctx), n)) : (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_getsize(a) (sizeof(a) / sizeof(a[0]))
|
||||
#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_def(ctx, n, def)(arg_get_int_count((ctx), (n)) ? (arg_get_int((ctx), (n))) : (def))
|
||||
|
||||
#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_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 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 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 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 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 {
|
||||
void **argtable;
|
||||
|
|
|
@ -32,7 +32,7 @@ device-side.
|
|||
local function calypso_parse(result)
|
||||
local r = Command.parse(result)
|
||||
if r.arg1 >= 0 then
|
||||
local len = r.arg2 * 2
|
||||
local len = r.arg1 * 2
|
||||
if len > 0 then
|
||||
r.data = string.sub(r.data, 0, len);
|
||||
return r, nil
|
||||
|
@ -113,8 +113,9 @@ end
|
|||
local function calypso_send_cmd_raw(data, ignoreresponse )
|
||||
|
||||
local command, flags, result, err
|
||||
flags = lib14b.ISO14B_COMMAND.ISO14B_RAW +
|
||||
lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC
|
||||
flags = lib14b.ISO14B_COMMAND.ISO14B_APDU
|
||||
-- flags = lib14b.ISO14B_COMMAND.ISO14B_RAW +
|
||||
-- lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC
|
||||
|
||||
data = data or "00"
|
||||
|
||||
|
@ -162,6 +163,7 @@ local function calypso_apdu_status(apdu)
|
|||
return status, desc, err
|
||||
end
|
||||
|
||||
local CLA = '94'
|
||||
local _calypso_cmds = {
|
||||
|
||||
-- Break down of command bytes:
|
||||
|
@ -184,27 +186,25 @@ local _calypso_cmds = {
|
|||
-- Electronic Purse file
|
||||
-- Electronic Transaction log file
|
||||
|
||||
|
||||
--['01.Select ICC file'] = '0294 a4 00 0002 3f00',
|
||||
['01.Select ICC file'] = '0294 a4 080004 3f00 0002',
|
||||
['02.ICC'] = '0394 b2 01 041d',
|
||||
['03.Select EnvHol file'] = '0294 a4 080004 2000 2001',
|
||||
['04.EnvHol1'] = '0394 b2 01 041d',
|
||||
['05.Select EvLog file'] = '0294 a4 080004 2000 2010',
|
||||
['06.EvLog1'] = '0394 b2 01 041d',
|
||||
['07.EvLog2'] = '0294 b2 02 041d',
|
||||
['08.EvLog3'] = '0394 b2 03 041d',
|
||||
['09.Select ConList file']= '0294 a4 080004 2000 2050',
|
||||
['10.ConList'] = '0394 b2 01 041d',
|
||||
['11.Select Contra file'] = '0294 a4 080004 2000 2020',
|
||||
['12.Contra1'] = '0394 b2 01 041d',
|
||||
['13.Contra2'] = '0294 b2 02 041d',
|
||||
['14.Contra3'] = '0394 b2 03 041d',
|
||||
['15.Contra4'] = '0294 b2 04 041d',
|
||||
['16.Select Counter file']= '0394 a4 080004 2000 2069',
|
||||
['17.Counter'] = '0294 b2 01 041d',
|
||||
['18.Select SpecEv file'] = '0394 a4 080004 2000 2040',
|
||||
['19.SpecEv1'] = '0294 b2 01 041d',
|
||||
['01.Select ICC file'] = CLA..'a4 080004 3f00 0002',
|
||||
['02.ICC'] = CLA..'b2 01 041d',
|
||||
['03.Select EnvHol file'] = CLA..'a4 080004 2000 2001',
|
||||
['04.EnvHol1'] = CLA..'b2 01 041d',
|
||||
['05.Select EvLog file'] = CLA..'a4 080004 2000 2010',
|
||||
['06.EvLog1'] = CLA..'b2 01 041d',
|
||||
['07.EvLog2'] = CLA..'b2 02 041d',
|
||||
['08.EvLog3'] = CLA..'b2 03 041d',
|
||||
['09.Select ConList file']= CLA..'a4 080004 2000 2050',
|
||||
['10.ConList'] = CLA..'b2 01 041d',
|
||||
['11.Select Contra file'] = CLA..'a4 080004 2000 2020',
|
||||
['12.Contra1'] = CLA..'b2 01 041d',
|
||||
['13.Contra2'] = CLA..'b2 02 041d',
|
||||
['14.Contra3'] = CLA..'b2 03 041d',
|
||||
['15.Contra4'] = CLA..'b2 04 041d',
|
||||
['16.Select Counter file']= CLA..'a4 080004 2000 2069',
|
||||
['17.Counter'] = CLA..'b2 01 041d',
|
||||
['18.Select SpecEv file'] = CLA..'a4 080004 2000 2040',
|
||||
['19.SpecEv1'] = CLA..'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
|
||||
print('Uploading dictionaries to RDV4 flashmemory')
|
||||
print(dash)
|
||||
core.console('mem load f mfc_default_keys m')
|
||||
core.console('mem load f t55xx_default_pwds t')
|
||||
core.console('mem load f iclass_default_keys i')
|
||||
core.console('mem load -f mfc_default_keys --mfc')
|
||||
core.console('mem load -f t55xx_default_pwds --t55xx')
|
||||
core.console('mem load -f iclass_default_keys --iclass')
|
||||
print(dash)
|
||||
|
||||
-- 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");
|
||||
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) {
|
||||
PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o <offset> l <length>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
|
@ -1825,7 +1811,8 @@ static int CmdMtrim(const char *Cmd) {
|
|||
uint32_t start = 0, stop = 0;
|
||||
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
|
||||
start++;
|
||||
|
@ -1912,14 +1899,32 @@ int CmdSave(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);
|
||||
if (CursorScaleFactor == 0) {
|
||||
PrintAndLogEx(FAILED, "bad, can't have zero scale");
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "data 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;
|
||||
}
|
||||
int len = 0;
|
||||
CursorScaleFactorUnit[0] = '\x00';
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t*)CursorScaleFactorUnit, sizeof(CursorScaleFactorUnit), &len);
|
||||
CLIParserFree(ctx);
|
||||
RepaintGraphWindow();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -8,16 +8,13 @@
|
|||
// Proxmark3 RDV40 Flash memory commands
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "cmdflashmem.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "cmdparser.h" // command_t
|
||||
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "cliparser.h"
|
||||
#include "pmflash.h"
|
||||
#include "fileutils.h" //saveFile
|
||||
#include "comms.h" //getfromdevice
|
||||
#include "fileutils.h" // saveFile
|
||||
#include "comms.h" // getfromdevice
|
||||
#include "cmdflashmemspiffs.h" // spiffs commands
|
||||
|
||||
#include "rsa.h"
|
||||
#include "sha1.h"
|
||||
|
||||
|
@ -29,90 +26,34 @@
|
|||
|
||||
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) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem baudrate",
|
||||
"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);
|
||||
|
||||
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) < 1 || ctmp == 'h') {
|
||||
return usage_flashmem_spibaud();
|
||||
if (br == -1) {
|
||||
PrintAndLogEx(ERR, "failed to get baudrate");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10);
|
||||
baudrate = baudrate * 1000000;
|
||||
uint32_t baudrate = br * 1000000;
|
||||
if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD) {
|
||||
usage_flashmem_spibaud();
|
||||
PrintAndLogEx(ERR, "wrong baudrate. Only 24 or 48 is allowed");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
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) {
|
||||
|
||||
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};
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
Dictionary_t d = DICTIONARY_NONE;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_flashmem_load();
|
||||
case 'f':
|
||||
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
|
||||
PrintAndLogEx(FAILED, "Filename too long");
|
||||
errors = true;
|
||||
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;
|
||||
}
|
||||
if (is_mfc) {
|
||||
d = DICTIONARY_MIFARE;
|
||||
PrintAndLogEx(INFO, "treating file as MIFARE Classic keys");
|
||||
} else if (is_iclass) {
|
||||
d = DICTIONARY_ICLASS;
|
||||
PrintAndLogEx(INFO, "treating file as iCLASS keys");
|
||||
} else if (is_t55xx) {
|
||||
d = DICTIONARY_T55XX;
|
||||
PrintAndLogEx(INFO, "treating file as T55xx passwords");
|
||||
}
|
||||
|
||||
//Validations
|
||||
if (errors || cmdp == 0) {
|
||||
usage_flashmem_load();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
size_t datalen = 0;
|
||||
uint32_t keycount = 0;
|
||||
int res = 0;
|
||||
|
@ -174,7 +113,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
|
||||
switch (d) {
|
||||
case DICTIONARY_MIFARE:
|
||||
start_index = DEFAULT_MF_KEYS_OFFSET;
|
||||
offset = DEFAULT_MF_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 6, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
|
@ -189,7 +128,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
datalen += 2;
|
||||
break;
|
||||
case DICTIONARY_T55XX:
|
||||
start_index = DEFAULT_T55XX_KEYS_OFFSET;
|
||||
offset = DEFAULT_T55XX_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 4, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
|
@ -204,7 +143,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
datalen += 2;
|
||||
break;
|
||||
case DICTIONARY_ICLASS:
|
||||
start_index = DEFAULT_ICLASS_KEYS_OFFSET;
|
||||
offset = DEFAULT_ICLASS_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 8, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
|
@ -253,13 +192,13 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
|
||||
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_sent += bytes_in_packet;
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
conn.block_after_ACK = false;
|
||||
free(data);
|
||||
|
@ -276,54 +215,37 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
|
||||
conn.block_after_ACK = false;
|
||||
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;
|
||||
}
|
||||
|
||||
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};
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
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;
|
||||
}
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint8_t *dump = calloc(len, sizeof(uint8_t));
|
||||
if (!dump) {
|
||||
|
@ -331,14 +253,15 @@ static int CmdFlashMemDump(const char *Cmd) {
|
|||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flashmem", len);
|
||||
if (!GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, 0, NULL, -1, true)) {
|
||||
PrintAndLogEx(FAILED, "ERROR; downloading from flashmemory");
|
||||
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flash memory", len);
|
||||
if (!GetFromDevice(FLASH_MEM, dump, len, offset, NULL, 0, NULL, -1, true)) {
|
||||
PrintAndLogEx(FAILED, "ERROR; downloading from flash memory");
|
||||
free(dump);
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
||||
if (print) {
|
||||
if (view) {
|
||||
PrintAndLogEx(INFO, "---- " _CYAN_("data") " ---------------");
|
||||
print_hex_break(dump, len, 32);
|
||||
}
|
||||
|
||||
|
@ -350,39 +273,32 @@ static int CmdFlashMemDump(const char *Cmd) {
|
|||
free(dump);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemWipe(const char *Cmd) {
|
||||
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
bool initalwipe = false;
|
||||
uint8_t page = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem wipe",
|
||||
"Wipe flash memory on device, which fills it with 0xFF\n"
|
||||
_WHITE_("[ ") _RED_("!!! OBS") " ] use with caution",
|
||||
"mem wipe -p 0 -> wipes first page"
|
||||
// "mem wipe -i -> inital total wipe"
|
||||
);
|
||||
|
||||
//Validations
|
||||
if (errors || cmdp == 0) {
|
||||
usage_flashmem_wipe();
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -393,59 +309,51 @@ static int CmdFlashMemWipe(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
const char* msg = "Flash WIPE ";
|
||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||
if (isok)
|
||||
PrintAndLogEx(SUCCESS, "Flash WIPE ok");
|
||||
PrintAndLogEx(SUCCESS, "%s ( " _GREEN_("ok")" )", msg);
|
||||
else {
|
||||
PrintAndLogEx(FAILED, "Flash WIPE failed");
|
||||
PrintAndLogEx(FAILED, "%s ( " _RED_("failed") " )", msg);
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemInfo(const char *Cmd) {
|
||||
|
||||
uint8_t sha_hash[20] = {0};
|
||||
mbedtls_rsa_context rsa;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem info",
|
||||
"Collect signature and verify it from flash memory",
|
||||
"mem info"
|
||||
// "mem info -s"
|
||||
);
|
||||
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false, shall_write = false, shall_sign = false;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_flashmem_info();
|
||||
case 's': {
|
||||
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;
|
||||
}
|
||||
}
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
// arg_lit0("s", NULL, "create a signature"),
|
||||
// arg_lit0("w", NULL, "write signature to flash memory"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
//Validations
|
||||
if (errors) {
|
||||
usage_flashmem_info();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
bool shall_sign = false, shall_write = false;
|
||||
// shall_sign = arg_get_lit(ctx, 1);
|
||||
// shall_write = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||
if (!isok) {
|
||||
if (isok == false) {
|
||||
PrintAndLogEx(FAILED, "failed");
|
||||
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));
|
||||
|
||||
// Flash ID hash (sha1)
|
||||
uint8_t sha_hash[20] = {0};
|
||||
mbedtls_sha1(mem.flashid, sizeof(mem.flashid), sha_hash);
|
||||
|
||||
// print header
|
||||
PrintAndLogEx(INFO, "\n--- Flash memory Information ---------");
|
||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||
PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid)));
|
||||
PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash)));
|
||||
PrintAndLogEx(INFO, "RSA SIGNATURE |");
|
||||
print_hex_break(mem.signature, sizeof(mem.signature), 32);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
|
||||
// PrintAndLogEx(INFO, "-----------------------------------------------------------------");
|
||||
PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid)));
|
||||
PrintAndLogEx(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
||||
PrintAndLogEx(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
|
||||
|
@ -473,7 +386,10 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
#define RSA_E "010001"
|
||||
|
||||
// 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)
|
||||
|
@ -516,9 +432,9 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
|
||||
"A74206CEC169D74BF5A8C50D6F48EA08"
|
||||
|
||||
|
||||
#define KEY_LEN 128
|
||||
|
||||
mbedtls_rsa_context rsa;
|
||||
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
||||
|
||||
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.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);
|
||||
|
||||
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)
|
||||
PrintAndLogEx(SUCCESS, "RSA key validation ok");
|
||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgkey);
|
||||
else
|
||||
PrintAndLogEx(FAILED, "RSA key validation failed");
|
||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgkey);
|
||||
|
||||
//
|
||||
uint8_t from_device[KEY_LEN];
|
||||
|
@ -554,10 +488,11 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
if (shall_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)
|
||||
PrintAndLogEx(SUCCESS, "RSA Signing ok");
|
||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgsign);
|
||||
else
|
||||
PrintAndLogEx(FAILED, "RSA Signing failed");
|
||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgsign);
|
||||
|
||||
if (shall_write) {
|
||||
// save to mem
|
||||
|
@ -574,29 +509,33 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
|
||||
}
|
||||
}
|
||||
PrintAndLogEx(INFO, "Signed | ");
|
||||
print_hex_break(sign, sizeof(sign), 32);
|
||||
PrintAndLogEx(INFO, "Signed");
|
||||
for (int i = 0; i < (sizeof(sign) / 32); i++) {
|
||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32));
|
||||
}
|
||||
}
|
||||
|
||||
// Verify (public key)
|
||||
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)
|
||||
PrintAndLogEx(SUCCESS, "RSA Verification ok");
|
||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgverify);
|
||||
else
|
||||
PrintAndLogEx(FAILED, "RSA Verification failed");
|
||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgverify);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation [rdv40]"},
|
||||
{"spibaud", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate [rdv40]"},
|
||||
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information [rdv40]"},
|
||||
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory [rdv40]"},
|
||||
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory [rdv40]"},
|
||||
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory [rdv40]"},
|
||||
{"baudrate", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate"},
|
||||
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation"},
|
||||
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"},
|
||||
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory"},
|
||||
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"},
|
||||
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory"},
|
||||
{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];
|
||||
}
|
||||
|
||||
static bool wait_cmd_14b(bool verbose) {
|
||||
static bool wait_cmd_14b(bool verbose, bool is_select) {
|
||||
|
||||
PacketResponseNG resp;
|
||||
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);
|
||||
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 (len >= 3) {
|
||||
|
@ -121,12 +138,14 @@ static int CmdHF14BSim(const char *Cmd) {
|
|||
|
||||
uint8_t pupi[4];
|
||||
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);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi));
|
||||
|
||||
SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -161,27 +180,26 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14b raw",
|
||||
"Sends raw bytes to card ",
|
||||
"hf 14b raw -s -c -k 0200a40400\n"
|
||||
"hf 14b raw --sr -c -k 0200a40400\n"
|
||||
"hf 14b raw --cts -c -k 0200a40400\n"
|
||||
"hf 14b raw -cks --data 0200a40400 -> standard select\n"
|
||||
"hf 14b raw -ck --sr --data 0200a40400 -> SRx select\n"
|
||||
"hf 14b raw -ck --cts --data 0200a40400 -> C-ticket select\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
|
||||
arg_lit0("s", "std", "activate field and select standard card"),
|
||||
arg_lit0(NULL, "sr", "activate field and select SRx ST"),
|
||||
arg_lit0(NULL, "cts", "activate field and select ASK C-ticket"),
|
||||
arg_lit0("c", "crc", "calculate and append CRC"),
|
||||
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
|
||||
arg_lit0("s", "std", "activate field and select standard card"),
|
||||
arg_lit0(NULL, "sr", "activate field and select SRx ST"),
|
||||
arg_lit0(NULL, "cts", "activate field and select ASK C-ticket"),
|
||||
arg_lit0("c", "crc", "calculate and append CRC"),
|
||||
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_strx0(NULL, NULL, "<data (hex)>", "bytes to send"),
|
||||
arg_strx0("d", "data", "<hex>", "data, bytes to send"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
bool select = false;
|
||||
bool keep_field_on = arg_get_lit(ctx, 1);
|
||||
bool select_std = arg_get_lit(ctx, 2);
|
||||
bool select_sr = arg_get_lit(ctx, 3);
|
||||
|
@ -197,25 +215,25 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
|||
}
|
||||
|
||||
if (select_std) {
|
||||
select = true;
|
||||
flags |= ISO14B_SELECT_STD;
|
||||
flags |= (ISO14B_SELECT_STD | ISO14B_CLEARTRACE);
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "using standard select");
|
||||
} else if (select_sr) {
|
||||
select = true;
|
||||
flags |= ISO14B_SELECT_SR;
|
||||
flags |= (ISO14B_SELECT_SR | ISO14B_CLEARTRACE);
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "using SRx ST select");
|
||||
PrintAndLogEx(INFO, "using ST/SRx select");
|
||||
} else if (select_cts) {
|
||||
select = true;
|
||||
flags |= ISO14B_SELECT_CTS;
|
||||
flags |= (ISO14B_SELECT_CTS | ISO14B_CLEARTRACE);
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "using ASK C-ticket select");
|
||||
PrintAndLogEx(INFO, "using ASK/C-ticket select");
|
||||
}
|
||||
|
||||
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
|
||||
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);
|
||||
|
||||
uint32_t time_wait = 0;
|
||||
|
@ -244,18 +262,33 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, datalen, time_wait, data, datalen);
|
||||
if (read_reply == false) {
|
||||
clearCommandBuffer();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
// get back iso14b_card_select_t, don't print it.
|
||||
if (select) {
|
||||
success = wait_cmd_14b(verbose);
|
||||
bool success = true;
|
||||
// Select, device will send back iso14b_card_select_t, don't print it.
|
||||
if (select_std) {
|
||||
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.
|
||||
if (success && datalen > 0) {
|
||||
wait_cmd_14b(true);
|
||||
wait_cmd_14b(true, false);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1525,10 +1558,10 @@ static int CmdHF14BAPDU(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
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",
|
||||
"hf 14b apdu -s 94a40800043f000002\n"
|
||||
"hf 14b apdu -sd 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
|
||||
"hf 14b apdu -sm 00A40400 325041592E5359532E4444463031 -l 256 -> encode standard apdu\n"
|
||||
"hf 14b apdu -sm 00A40400 325041592E5359532E4444463031 -el 65536 -> encode extended apdu\n");
|
||||
"hf 14b apdu -s --hex 94a40800043f000002\n"
|
||||
"hf 14b apdu -sd --hex 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
|
||||
"hf 14b apdu -sm 00A40400 -l 256 --hex 325041592E5359532E4444463031 -> encode standard apdu\n"
|
||||
"hf 14b apdu -sm 00A40400 -el 65536 --hex 325041592E5359532E4444463031 -> encode extended apdu\n");
|
||||
|
||||
void *argtable[] = {
|
||||
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("t", "tlv", "executes TLV decoder 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_int0("l", "le", "<Le (int)>", "Le apdu parameter if `m` parameter included"),
|
||||
arg_strx1(NULL, NULL, "<APDU (hex) | data (hex)>", "data if `m` parameter included"),
|
||||
arg_int0("l", "le", "<int>", "Le apdu parameter if `m` parameter included"),
|
||||
arg_strx1(NULL, "hex", "<hex>", "<APDU | data> if `m` parameter included"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -325,8 +325,8 @@ static int cmd_hf_st_sim(const char *Cmd) {
|
|||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (uidlen != 7) {
|
||||
PrintAndLogEx(ERR, "UID must be 7 hex bytes");
|
||||
|
@ -350,12 +350,12 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("p", "password", "<hex>", "16 byte read password"),
|
||||
arg_str0("p", "pwd", "<hex>", "16 byte read password"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 1, pwd, &pwdlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (pwdlen == 0) {
|
||||
with_pwd = false;
|
||||
|
@ -483,13 +483,10 @@ static int cmd_hf_st_protect(const char *Cmd) {
|
|||
disable_protection = arg_get_lit(ctx, 2);
|
||||
read_protection = arg_get_lit(ctx, 3);
|
||||
write_protection = arg_get_lit(ctx, 4);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 5, pwd, &pwdlen);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
//Validations
|
||||
|
||||
if (enable_protection && disable_protection) {
|
||||
PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both");
|
||||
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_write_password = arg_get_lit(ctx, 2);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 3, pwd, &pwdlen);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 4, newpwd, &newpwdlen);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (change_read_password && change_write_password) {
|
||||
PrintAndLogEx(ERR, "Must specify either read or write, not both");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
} else {
|
||||
if (change_read_password) {
|
||||
|
@ -643,8 +638,6 @@ static int cmd_hf_st_pwd(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (pwdlen != 16) {
|
||||
PrintAndLogEx(ERR, "Original write password must be 16 hex bytes");
|
||||
return PM3_EINVARG;
|
||||
|
@ -727,9 +720,7 @@ static int cmd_hf_st_pwd(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, " %s password changed", ((changePwd[2] & 0x01) == 0x01) ? _YELLOW_("read") : _YELLOW_("write"));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
static int cmd_hf_st_list(const char *Cmd) {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "cmdparser.h" // command_t
|
||||
#include "comms.h"
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
#include "cliparser.h"
|
||||
#include "ui.h"
|
||||
#include "graph.h"
|
||||
#include "cmddata.h" //for g_debugMode, demodbuff cmds
|
||||
|
@ -43,70 +44,6 @@
|
|||
|
||||
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?
|
||||
static int sendPing(void) {
|
||||
SendCommandNG(CMD_PING, NULL, 0);
|
||||
|
@ -276,8 +213,20 @@ static int CmdHIDRead(const char *Cmd) {
|
|||
// this read loops on device side.
|
||||
// uses the demod in lfops.c
|
||||
static int CmdHIDWatch(const char *Cmd) {
|
||||
uint8_t c = tolower(param_getchar(Cmd, 0));
|
||||
if (c == 'h') return usage_lf_hid_watch();
|
||||
CLIParserContext *ctx;
|
||||
|
||||
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(INFO, "Press pm3-button to stop reading cards");
|
||||
|
@ -290,28 +239,52 @@ static int CmdHIDWatch(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int CmdHIDSim(const char *Cmd) {
|
||||
int idlen = 0;
|
||||
uint8_t id[10] = {0};
|
||||
lf_hidsim_t payload;
|
||||
payload.longFMT = 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));
|
||||
if (strlen(Cmd) == 0 || ctmp == 'h') return usage_lf_hid_sim();
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf hid sim",
|
||||
"Enables simulation of HID card with card number.",
|
||||
"lf hid sim 2006ec0c86"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
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);
|
||||
|
||||
if (strchr(Cmd, 'l') != 0) {
|
||||
i++;
|
||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
||||
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);
|
||||
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);
|
||||
payload.longFMT = 1;
|
||||
} else {
|
||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
||||
for (i=0; i < idlen; ++i) {
|
||||
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);
|
||||
hi2 = 0;
|
||||
|
@ -334,28 +307,55 @@ static int CmdHIDSim(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 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};
|
||||
if (strchr(Cmd, 'l') != 0) {
|
||||
i++;
|
||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
||||
|
||||
if (long_id) {
|
||||
for (i=0; i < idlen; ++i) {
|
||||
hi2 = (hi2 << 4) | (hi >> 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);
|
||||
|
||||
longid[0] = 1;
|
||||
} else {
|
||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
||||
for (i=0; i < idlen; ++i) {
|
||||
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);
|
||||
hi2 = 0;
|
||||
|
@ -385,82 +385,63 @@ static int CmdHIDClone(const char *Cmd) {
|
|||
|
||||
static int CmdHIDBrute(const char *Cmd) {
|
||||
|
||||
bool errors = false, verbose = false;
|
||||
uint32_t delay = 1000;
|
||||
uint8_t cmdp = 0;
|
||||
int format_idx = -1;
|
||||
int direction = 0;
|
||||
char format[16] = {0};
|
||||
uint8_t format[16] = {0};
|
||||
int formatLen;
|
||||
|
||||
wiegand_card_t cn_hi, cn_low;
|
||||
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"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("v", "verbose", "verbose logging, show all tries"),
|
||||
arg_str1("w", "wiegand", "format", "see " _YELLOW_("`wiegand list`") " for available formats"),
|
||||
arg_int0("f", "fn", "dec", "facility code"),
|
||||
arg_int0("c", "cn", "dec", "card number to start with"),
|
||||
arg_int0("i", NULL, "dec", "issue level"),
|
||||
arg_int0("o", "oem", "dec", "OEM code"),
|
||||
arg_int0("d", "delay", "dec", "delay betweens attempts in ms. Default 1000ms"),
|
||||
arg_lit0(NULL, "up", "direction to increment card number. (default is both directions)"),
|
||||
arg_lit0(NULL, "down", "direction to decrement card number. (default is both directions)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
char s[10] = {0};
|
||||
if (param_getstr(Cmd, cmdp, s, sizeof(s)) > 0) {
|
||||
if (strlen(s) > 1) {
|
||||
str_lower((char *)s);
|
||||
if (str_startswith(s, "up")) {
|
||||
direction = 1;
|
||||
} else if (str_startswith(s, "do")) {
|
||||
direction = 2;
|
||||
}
|
||||
cmdp++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
bool verbose = arg_get_lit(ctx, 1);
|
||||
|
||||
CLIGetStrWithReturn(ctx, 2, format, &formatLen);
|
||||
|
||||
format_idx = HIDFindCardFormat((char*) format);
|
||||
if (format_idx == -1) {
|
||||
PrintAndLogEx(ERR, "You must select a wiegand format. See " _YELLOW_("`wiegand list`") " for available formats\n");
|
||||
errors = true;
|
||||
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
|
||||
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) {
|
||||
PrintAndLogEx(INFO, "Wiegand format#.. %i", format_idx);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "cliparser.h"
|
||||
#include "comms.h"
|
||||
#include "ui.h"
|
||||
#include "cmddata.h"
|
||||
|
@ -26,43 +27,6 @@
|
|||
#include "cmdlft55xx.h" // verifywrite
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
|
||||
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 cid = 0;
|
||||
uint32_t internalid = 0;
|
||||
|
@ -240,42 +205,35 @@ static int CmdKeriClone(const char *Cmd) {
|
|||
// dynamic bitrate used
|
||||
blocks[0] |= 0xF << 18;
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_clone();
|
||||
CLIParserContext *ctx;
|
||||
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
|
||||
cid = param_get32ex(Cmd, 0, 0, 10);
|
||||
|
||||
// find other options
|
||||
while (param_getchar(Cmd, cmdidx) != 0x00) { // && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdidx))) {
|
||||
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++;
|
||||
}
|
||||
void *argtable[] = {
|
||||
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);
|
||||
|
||||
if (arg_get_lit(ctx, 1)) {
|
||||
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
|
||||
q5 = true;
|
||||
}
|
||||
|
||||
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
|
||||
switch (keritype) {
|
||||
switch (keritype[0]) {
|
||||
case 'i' : // Internal ID
|
||||
// MSB is ONE
|
||||
internalid = cid | 0x80000000;
|
||||
|
@ -283,6 +241,9 @@ static int CmdKeriClone(const char *Cmd) {
|
|||
case 'm' : // MS
|
||||
CmdKeriMSScramble(Scramble, &fc, &cid, &internalid);
|
||||
break;
|
||||
default :
|
||||
PrintAndLogEx(ERR, "Invalid type");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// Prepare and write to card
|
||||
|
@ -303,11 +264,23 @@ static int CmdKeriClone(const char *Cmd) {
|
|||
|
||||
static int CmdKeriSim(const char *Cmd) {
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) == 0 || cmdp == 'h')
|
||||
return usage_lf_keri_sim();
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "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 = param_get32ex(Cmd, 0, 0, 10);
|
||||
uint64_t internalid = arg_get_int_def(ctx, 1, 0);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
internalid |= 0x80000000;
|
||||
internalid <<= 3;
|
||||
internalid += 7;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "cliparser.h"
|
||||
#include "comms.h"
|
||||
#include "pm3_cmd.h"
|
||||
#include "protocols.h"
|
||||
|
@ -24,172 +25,134 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int usage_wiegand_list(void) {
|
||||
PrintAndLogEx(NORMAL, "List available wiegand formats");
|
||||
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) {
|
||||
static void print_wiegand_code(wiegand_message_t *packed) {
|
||||
const char* s = "Encoded wiegand: ";
|
||||
if (packed->Top != 0) {
|
||||
PrintAndLogEx(SUCCESS, "Card ID: %X%08X%08X",
|
||||
(uint32_t)packed->Top,
|
||||
(uint32_t)packed->Mid,
|
||||
(uint32_t)packed->Bot)
|
||||
;
|
||||
PrintAndLogEx(SUCCESS, "%s" _GREEN_("%X%08X%08X"),
|
||||
s,
|
||||
(uint32_t)packed->Top,
|
||||
(uint32_t)packed->Mid,
|
||||
(uint32_t)packed->Bot
|
||||
);
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, "Card ID: %X%08X",
|
||||
(uint32_t)packed->Mid,
|
||||
(uint32_t)packed->Bot)
|
||||
;
|
||||
PrintAndLogEx(SUCCESS, "%s" _YELLOW_("%X%08X"),
|
||||
s,
|
||||
(uint32_t)packed->Mid,
|
||||
(uint32_t)packed->Bot
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
int CmdWiegandList(const char *Cmd) {
|
||||
bool errors = false;
|
||||
char cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_wiegand_list();
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "wiegand info",
|
||||
"List available wiegand formats",
|
||||
"wiegand list"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
HIDListFormats();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdWiegandEncode(const char *Cmd) {
|
||||
|
||||
int format_idx = -1;
|
||||
char format[16] = {0};
|
||||
CLIParserContext *ctx;
|
||||
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;
|
||||
memset(&data, 0, sizeof(wiegand_card_t));
|
||||
|
||||
data.FacilityCode = arg_get_u32_def(ctx, 1, 0);
|
||||
data.CardNumber = arg_get_u64_def(ctx, 2, 0);
|
||||
data.IssueLevel = arg_get_u32_def(ctx, 3, 0);
|
||||
data.OEM = arg_get_u32_def(ctx, 4, 0);
|
||||
|
||||
int len = 0;
|
||||
char format[16] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t*)format, sizeof(format), &len);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
bool errors = false;
|
||||
char cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_wiegand_encode();
|
||||
case 'w':
|
||||
param_getstr(Cmd, cmdp + 1, format, sizeof(format));
|
||||
format_idx = HIDFindCardFormat(format);
|
||||
if (format_idx == -1) {
|
||||
PrintAndLogEx(WARNING, "Unknown format: %s", format);
|
||||
errors = true;
|
||||
}
|
||||
cmdp += 2;
|
||||
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;
|
||||
}
|
||||
int idx = HIDFindCardFormat(format);
|
||||
if (idx == -1) {
|
||||
PrintAndLogEx(WARNING, "Unknown format: %s", format);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
if (errors || cmdp == 0) return usage_wiegand_encode();
|
||||
|
||||
wiegand_message_t packed;
|
||||
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.");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
PrintTagId(&packed);
|
||||
print_wiegand_code(&packed);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdWiegandDecode(const char *Cmd) {
|
||||
|
||||
uint32_t top = 0, mid = 0, bot = 0;
|
||||
bool ignore_parity = false, gothex = false;
|
||||
bool errors = false;
|
||||
char cmdp = 0;
|
||||
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;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "wiegand decode",
|
||||
"Decode raw hex to wiegand format",
|
||||
"wiegand decode --raw 2006f623ae"
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
HIDTryUnpack(&packed, ignore_parity);
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"list", CmdWiegandList, AlwaysAvailable, "List available wiegand formats"},
|
||||
{"encode", CmdWiegandEncode, AlwaysAvailable, "Convert "},
|
||||
{"decode", CmdWiegandDecode, AlwaysAvailable, "Convert raw hex to wiegand format"},
|
||||
{"encode", CmdWiegandEncode, AlwaysAvailable, "Encode to wiegand raw hex"},
|
||||
{"decode", CmdWiegandDecode, AlwaysAvailable, "Convert raw hex to decoded wiegand format"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ void InitGraphics(int argc, char **argv, char *script_cmds_file, char *script_cm
|
|||
void ExitGraphics(void);
|
||||
|
||||
extern double CursorScaleFactor;
|
||||
extern char CursorScaleFactorUnit[11];
|
||||
extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, GridOffset;
|
||||
extern uint32_t CursorCPos, CursorDPos;
|
||||
extern int CommandFinished;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// GUI (QT)
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "proxguiqt.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <iostream>
|
||||
#include <QPainterPath>
|
||||
|
@ -424,7 +424,8 @@ void Plot::PlotGraph(int *buffer, size_t len, QRect plotRect, QRect annotationRe
|
|||
if (len == 0) return;
|
||||
// clock_t begin = clock();
|
||||
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;
|
||||
int x = xCoordOf(GraphStart, plotRect);
|
||||
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;
|
||||
vMean += v;
|
||||
}
|
||||
vMean /= (i - GraphStart);
|
||||
GraphStop = i;
|
||||
vMean /= (GraphStop - GraphStart);
|
||||
|
||||
painter->setPen(getColor(graphNum));
|
||||
|
||||
|
@ -483,10 +485,9 @@ void Plot::PlotGraph(int *buffer, size_t len, QRect plotRect, QRect annotationRe
|
|||
//Graph annotations
|
||||
painter->drawPath(penPath);
|
||||
char str[200];
|
||||
sprintf(str, "max=%d min=%d mean=%d n=%u/%zu CursorAVal=[%d] CursorBVal=[%d]",
|
||||
vMax, vMin, vMean, i, len, buffer[CursorAPos], buffer[CursorBPos]);
|
||||
sprintf(str, "max=%d min=%d mean=%" PRId64 " n=%u/%zu CursorAVal=[%d] CursorBVal=[%d]",
|
||||
vMax, vMin, vMean, GraphStop - GraphStart, len, buffer[CursorAPos], buffer[CursorBPos]);
|
||||
painter->drawText(20, annotationRect.bottom() - 23 - 20 * graphNum, str);
|
||||
|
||||
//clock_t end = clock();
|
||||
//double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
//printf("Plot time %f\n", elapsed_secs);
|
||||
|
@ -596,10 +597,19 @@ void Plot::paintEvent(QPaintEvent *event) {
|
|||
|
||||
//Draw annotations
|
||||
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,
|
||||
GraphStop,
|
||||
CursorBPos - CursorAPos,
|
||||
((int32_t)(CursorBPos - CursorAPos)) / CursorScaleFactor,
|
||||
scalestr,
|
||||
GraphPixelsPerPoint,
|
||||
CursorAPos,
|
||||
CursorBPos,
|
||||
|
@ -637,7 +647,7 @@ void Plot::closeEvent(QCloseEvent *event) {
|
|||
g_useOverlays = false;
|
||||
}
|
||||
|
||||
void Plot::Zoom(float factor, int refX) {
|
||||
void Plot::Zoom(double factor, int refX) {
|
||||
if (factor >= 1) { // Zoom in
|
||||
if (GraphPixelsPerPoint <= 25 * 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) {
|
||||
// event->delta()
|
||||
// 120 => shift right 5%
|
||||
// -120 => shift left 5%
|
||||
const float move_offset = 0.05;
|
||||
// -120+shift => zoom in 10%
|
||||
// 120+shift => zoom out 10%
|
||||
const float zoom_offset = 0.1;
|
||||
// -120+shift => zoom in (5 times = *2)
|
||||
// 120+shift => zoom out (5 times = /2)
|
||||
const double zoom_offset = 1.148698354997035; // 2**(1/5)
|
||||
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
|
||||
#if QT_VERSION >= 0x050d00
|
||||
|
@ -697,10 +731,15 @@ void Plot::wheelEvent(QWheelEvent *event) {
|
|||
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
|
||||
#if QT_VERSION >= 0x050d00
|
||||
Zoom(1.0 - (float)event->angleDelta().y() / (120 / zoom_offset), x);
|
||||
float delta = event->angleDelta().y();
|
||||
#else
|
||||
Zoom(1.0 - (float)event->delta() / (120 / zoom_offset), x);
|
||||
float delta = event->delta();
|
||||
#endif
|
||||
if (delta < 0) {
|
||||
Zoom(zoom_offset, x);
|
||||
} else {
|
||||
Zoom(1.0 / zoom_offset, x);
|
||||
}
|
||||
} else {
|
||||
#if QT_VERSION >= 0x050d00
|
||||
Move(PageWidth * (-(float)event->angleDelta().y() / (120 / move_offset)));
|
||||
|
@ -794,6 +833,7 @@ void Plot::keyPressEvent(QKeyEvent *event) {
|
|||
puts("\tH Show help");
|
||||
puts("\tL Toggle lock grid relative to samples");
|
||||
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("\tEND Move to the end of the graph");
|
||||
puts("\tPGUP Page left");
|
||||
|
@ -823,6 +863,10 @@ void Plot::keyPressEvent(QKeyEvent *event) {
|
|||
master->hide();
|
||||
break;
|
||||
|
||||
case Qt::Key_T:
|
||||
Trim();
|
||||
break;
|
||||
|
||||
case Qt::Key_Home:
|
||||
GraphStart = 0;
|
||||
break;
|
||||
|
|
|
@ -32,6 +32,7 @@ class Plot: public QWidget {
|
|||
private:
|
||||
QWidget *master;
|
||||
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)
|
||||
uint32_t CursorAPos;
|
||||
uint32_t CursorBPos;
|
||||
|
@ -50,8 +51,9 @@ class Plot: public QWidget {
|
|||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void closeEvent(QCloseEvent *event);
|
||||
void Zoom(float factor, int refX);
|
||||
void Zoom(double factor, int refX);
|
||||
void Move(int offset);
|
||||
void Trim(void);
|
||||
void wheelEvent(QWheelEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event) { mouseMoveEvent(event); }
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
session_arg_t session;
|
||||
|
||||
double CursorScaleFactor = 1;
|
||||
char CursorScaleFactorUnit[11] = {0};
|
||||
int PlotGridX = 0, PlotGridY = 0, PlotGridXdefault = 64, PlotGridYdefault = 64;
|
||||
uint32_t CursorCPos = 0, CursorDPos = 0;
|
||||
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
|
||||
---
|
||||
w <format> o <OEM> f <FC> c <CN> i <issuelevel>
|
||||
w : wiegand format to use
|
||||
o : OEM number / site code
|
||||
f : facility code
|
||||
c : card number
|
||||
i : issue level
|
||||
-w <format> --oem <OEM> --fc <FC> --cn <CN> --issue <issuelevel>
|
||||
|
||||
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
|
||||
```
|
||||
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
|
||||
|
@ -379,14 +381,18 @@ Brute force HID reader
|
|||
```
|
||||
Options
|
||||
---
|
||||
a <format> : 26|33|34|35|37|40|44|84
|
||||
f <facility-code> : 8-bit value HID facility code
|
||||
c <cardnumber> : (optional) cardnumber to start with, max 65535
|
||||
d <delay> : delay betweens attempts in ms. Default 1000ms
|
||||
v : verbose logging, show all tries
|
||||
-v, --verbose : verbose logging, show all tries
|
||||
-w, --wiegand format : see `wiegand list` for available formats
|
||||
-f, --fn dec : facility code
|
||||
-c, --cn dec : card number to start with
|
||||
-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 v a 26 f 21 c 200 d 2000
|
||||
pm3 --> lf hid brute -w H10301 -f 224
|
||||
pm3 --> lf hid brute -v -w H10301 -f 21 -c 200 -d 2000
|
||||
```
|
||||
|
||||
## Indala
|
||||
|
@ -552,7 +558,7 @@ pm3 --> script list
|
|||
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
|
||||
---
|
||||
o <offset> : offset in memory
|
||||
f <filename> : file name
|
||||
m : upload 6 bytes keys (mifare key dictionary)
|
||||
i : upload 8 bytes keys (iClass key dictionary)
|
||||
t : upload 4 bytes keys (pwd dictionary)
|
||||
-o <offset> : offset in memory
|
||||
-f <filename> : file name
|
||||
--mfc : upload 6 bytes keys (mifare key dictionary)
|
||||
--iclass : upload 8 bytes keys (iClass key dictionary)
|
||||
--t55xx : upload 4 bytes keys (pwd dictionary)
|
||||
|
||||
pm3 --> mem load f mfc_default_keys m
|
||||
pm3 --> mem load f t55xx_default_pwds t
|
||||
pm3 --> mem load f iclass_default_keys i
|
||||
pm3 --> mem load -f mfc_default_keys --mfc
|
||||
pm3 --> mem load -f t55xx_default_pwds --t5xx
|
||||
pm3 --> mem load -f iclass_default_keys --iclass
|
||||
```
|
||||
|
||||
## Sim Module
|
||||
|
|
122
doc/cliparser.md
122
doc/cliparser.md
|
@ -13,26 +13,26 @@ lf config h H
|
|||
even the external tools which we collected into this repo, under folder */tools/* folder uses their own argument parsing.
|
||||
|
||||
|
||||
In order to counter this and unify it, there was discussion over at the official repository a few years ago [link to issue](https://github.com/Proxmark/proxmark3/issues/467) and there it became clear a change is needed. Among the different solutions suggested @merlokk's idea of using the lib cliparser was agreed upon. The lib was adapted and implemented for commands like
|
||||
In order to counter this and unify it, there was discussion over at the official repository a few years ago [link to issue](https://github.com/Proxmark/proxmark3/issues/467) and there it became clear a change is needed. Among the different solutions suggested @merlokk's idea of using the lib cliparser was agreed upon. The lib was adapted and implemented for commands like
|
||||
|
||||
```
|
||||
[usb] pm3 --> emv
|
||||
[usb] pm3 --> hf fido
|
||||
```
|
||||
|
||||
And then it fell into silence since it wasn't well documented how to use the cliparser. Looking at source code wasn't very efficient. However the need of a better cli parsing was still there.
|
||||
And then it fell into silence since it wasn't well documented how to use the cliparser. Looking at source code wasn't very efficient. However the need of a better cli parsing was still there.
|
||||
|
||||
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)
|
||||
|
||||
|
||||
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
|
||||
|
@ -42,11 +42,11 @@ It will also add the `-h --help` option automatic.
|
|||
|
||||
## design comments
|
||||
|
||||
* where possible all options should be lowercase.
|
||||
* extended options preceded with -- should be short
|
||||
* options provided directly (without an option identifier) should be avoided.
|
||||
* -vv for extra verbos 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 '='
|
||||
* where possible all options should be lowercase.
|
||||
* extended options preceded with -- should be short
|
||||
* options provided directly (without an option identifier) should be avoided.
|
||||
* -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 '='
|
||||
e.g. cmd --cn 12345
|
||||
|
||||
|
||||
|
@ -59,7 +59,7 @@ It will also add the `-h --help` option automatic.
|
|||
--raw : raw data
|
||||
-k --key : key supplied
|
||||
-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
|
||||
|
||||
|
||||
|
@ -77,14 +77,14 @@ In the command function, setup 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.
|
||||
e.g. lf indala clone -r a0000000a0002021 -> this uses .....
|
||||
|
||||
CLIParserInit(&ctx, "lf indala clone",
|
||||
"clone INDALA UID to T55x7 or Q5/T5555 tag",
|
||||
"lf indala clone --heden 888\n"
|
||||
CLIParserInit(&ctx, "lf indala clone",
|
||||
"clone INDALA UID to T55x7 or Q5/T5555 tag",
|
||||
"lf indala clone --heden 888\n"
|
||||
"lf indala clone --fc 123 --cn 1337\n"
|
||||
"lf indala clone -r a0000000a0002021\n"
|
||||
"lf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
|
||||
|
@ -93,9 +93,9 @@ e.g. lf indala clone -r a0000000a0002021 -> this uses .....
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("l", "long", "optional - long UID 224 bits"),
|
||||
arg_int0("c", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_lit0("l", "long", "optional - long UID 224 bits"),
|
||||
arg_int0("c", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
|
||||
arg_int0(NULL, "fc", "<decimal>", "Facility Code (26 bit format)"),
|
||||
arg_int0(NULL, "cn", "<decimal>", "Cardnumber (26 bit format)"),
|
||||
|
@ -103,75 +103,103 @@ 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.
|
||||
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:**
|
||||
**bool option. true if supplied**
|
||||
bool : arg_lit0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||
### Notes:
|
||||
#### bool option. true if supplied
|
||||
`bool : arg_lit0 ("<short option>", "<long option>", <"description">)`
|
||||
|
||||
**integer that is optional**
|
||||
optional integer : arg_int0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||
#### integer that is optional
|
||||
`optional integer : arg_int0 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||
|
||||
**integer that is required**
|
||||
required integer : arg_int1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||
#### integer that is required
|
||||
`required integer : arg_int1 ("<short option>", "<long option>", "<format>", <"description">)`
|
||||
|
||||
**String option that is optional and only one instance can be provided**
|
||||
optional string : arg_str0("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||
#### double that is optional
|
||||
`optional double : arg_dbl0 ("<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"\>)
|
||||
#### double that is required
|
||||
`required double : arg_dbl1 ("<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 optional and only one instance can be provided
|
||||
`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">)`
|
||||
|
||||
|
||||
**if an option does not have a short or long option, use NULL in its place**
|
||||
|
||||
**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**
|
||||
|
||||
### 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);
|
||||
|
||||
### clean up
|
||||
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.
|
||||
It will also add the `-h --help` option automatic.
|
||||
|
||||
|
||||
**bool option**
|
||||
**bool option**
|
||||
arg_get_lit(\<context\>, \<opt index\>);
|
||||
|
||||
is_long_uid = arg_get_lit(ctx, 1);
|
||||
|
||||
**int option**
|
||||
**int option**
|
||||
arg_get_int_def(\<context\>, \<opt index\>, \<default value\>);
|
||||
|
||||
cardnumber = arg_get_int_def(ctx, 2, -1);
|
||||
|
||||
**hex option**
|
||||
|
||||
**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**
|
||||
CLIGetHexWithReturn(\<context\>, \<opt index\>, \<store variable\>, \<ptr to stored length\>);
|
||||
?? as an array of uint_8 ??
|
||||
|
||||
|
||||
uint8_t aid[2] = {0};
|
||||
int aidlen;
|
||||
CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
|
||||
|
||||
**hex option returning ???**
|
||||
**hex option returning ???**
|
||||
|
||||
uint8_t key[24] = {0};
|
||||
int keylen = 0;
|
||||
int res_klen = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 24, &keylen);
|
||||
quick test : seems res_keylen == 0 when ok so not key len ???
|
||||
quick test : seems res_keylen == 0 when ok so not key len ???
|
||||
|
||||
**string option**
|
||||
**string option**
|
||||
CLIGetStrWithReturn(\<context\>,\<opt index\>, \<unsigned char \*\>, \<int \*\>);
|
||||
|
||||
uint8_t Buffer[100];
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef enum ISO14B_COMMAND {
|
|||
ISO14B_SET_TIMEOUT = (1 << 8),
|
||||
ISO14B_SEND_CHAINING = (1 << 9),
|
||||
ISO14B_SELECT_CTS = (1 << 10),
|
||||
ISO14B_CLEARTRACE = (1 << 11),
|
||||
} iso14b_command_t;
|
||||
|
||||
#endif // _ISO14B_H_
|
|
@ -32,7 +32,7 @@ lf hid clone 2006ec0c86
|
|||
lf read s 10000
|
||||
data save f lf_t5577_hid
|
||||
|
||||
lf hid clone l 2006ec0c86
|
||||
lf hid clone -l 2006ec0c86
|
||||
lf read s 20000
|
||||
data save f lf_t5577_hid_84
|
||||
|
||||
|
@ -56,15 +56,15 @@ lf jablotron clone 112233
|
|||
lf read s 16000
|
||||
data save f lf_t5577_jablotron
|
||||
|
||||
lf keri clone 112233
|
||||
lf keri clone --id 112233
|
||||
lf read s 10000
|
||||
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
|
||||
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
|
||||
data save f lf_t5577_keri_msid
|
||||
|
||||
|
|
Loading…
Reference in a new issue