Merge pull request #54 from RfidResearchGroup/master

Update
This commit is contained in:
mwalker33 2020-10-12 15:26:15 +11:00 committed by GitHub
commit 46fe7d1292
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
139 changed files with 25421 additions and 23275 deletions

1
.lsan_suppressions Normal file
View file

@ -0,0 +1 @@
leak:libfontconfig.so

View file

@ -248,7 +248,7 @@ print-%: ; @echo $* = $($*)
style:
# Make sure astyle is installed
@which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 )
# Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile
# Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile, *.v
find . \( -not -path "./cov-int/*" -and -not -path "./fpga/xst/*" -and \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \) \
-exec perl -pi -e 's/[ \t]+$$//' {} \; \
-exec sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \
@ -259,23 +259,32 @@ style:
--keep-one-line-blocks --max-instatement-indent=60 \
--style=google --pad-oper --unpad-paren --pad-header \
--align-pointer=name {} \;
# Update commands.md
[ -x client/proxmark3 ] && client/proxmark3 -m > doc/commands.md
# Detecting weird codepages and tabs.
ifeq ($(platform),Darwin)
miscchecks: TABSCMD=egrep -l '\t' {}
else
miscchecks: TABSCMD=grep -lP '\t' {}
endif
ifneq (,$(EDIT))
miscchecks: TABSCMD+= && vi {} -c ':set tabstop=4' -c ':set et|retab' -c ':wq'
endif
miscchecks:
# Make sure recode is installed
@which recode >/dev/null || ( echo "Please install 'recode' package first" ; exit 1 )
@echo "Files with suspicious chars:"
@find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \
@find . \( -not -path "./cov-int/*" -and -not -path "./client/deps/*" -and \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \) \
-exec sh -c "cat {} |recode utf8.. >/dev/null || echo {}" \;
@echo "Files with tabs:"
# to remove tabs within lines, one can try with: vi $file -c ':set tabstop=4' -c ':set et|retab' -c ':wq'
ifeq ($(platform),Darwin)
@find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \
-exec egrep -l '\t' {} \;
ifneq (,$(EDIT))
@echo "Files with tabs: (EDIT enabled, files will be rewritten!)"
else
@find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \
-exec grep -lP '\t' {} \;
@echo "Files with tabs: (rerun with EDIT=1 if you want to convert them with vim)"
endif
# to remove tabs within lines, one can try with: vi $file -c ':set tabstop=4' -c ':set et|retab' -c ':wq'
@find . \( -not -path "./cov-int/*" -and -not -path "./client/deps/*" -and \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \) \
-exec sh -c "$(TABSCMD)" \;
# @echo "Files with printf \\\\t:"
# @find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \
# -exec grep -lP '\\t' {} \;

View file

@ -50,6 +50,13 @@ endif
DEFCXXFLAGS = -Wall -Werror -O3 -pipe
DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe
DEFLDFLAGS =
# Next ones are activated only if SANITIZE=1
ifeq ($(SANITIZE),1)
DEFCFLAGS += -g -fsanitize=address -fno-omit-frame-pointer
DEFCXXFLAGS += -g -fsanitize=address -fno-omit-frame-pointer
DEFLDFLAGS += -g -fsanitize=address
endif
# Some more warnings we want as errors:
DEFCFLAGS += -Wbad-function-cast -Wredundant-decls -Wmissing-prototypes -Wchar-subscripts -Wshadow -Wundef -Wwrite-strings -Wunused -Wuninitialized -Wpointer-arith -Winline -Wformat -Wformat-security -Winit-self -Wmissing-include-dirs -Wnested-externs -Wmissing-declarations -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wtype-limits -Wold-style-definition
# Some more warnings we need first to eliminate, so temporarely tolerated:

View file

@ -19,6 +19,7 @@ CFLAGS ?= $(DEFCFLAGS)
CFLAGS += $(MYDEFS) $(MYCFLAGS) $(MYINCLUDES)
CXXFLAGS ?= $(DEFCXXFLAGS)
CXXFLAGS += $(MYDEFS) $(MYCXXFLAGS) $(MYINCLUDES)
LDFLAGS ?= $(DEFLDFLAGS)
LDFLAGS += $(MYLDFLAGS)
LDLIBS += $(MYLDLIBS)

View file

@ -30,7 +30,7 @@
| ------------------- |:-------------------:| -------------------:|
|[Notes on UART](/doc/uart_notes.md)|[Notes on Termux / Android](/doc/termux_notes.md)|[Notes on paths](/doc/path_notes.md)|
|[Notes on frame format](/doc/new_frame_format.md)|[Notes on tracelog / wireshark](/doc/trace_notes.md)|[Notes on EMV](/doc/emv_notes.md)|
|[Notes on external flash](/doc/ext_flash_notes.md)|[Notes on loclass](/doc/loclass_notes.md)|[Notes on Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md)|
|[Notes on external flash](/doc/ext_flash_notes.md)|[Notes on loclass](/doc/loclass_notes.md)|[Notes on Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-and-Run.md)|
|[Notes on file formats used with Proxmark3](/doc/extensions_notes.md)|[Notes on MFU binary format](/doc/mfu_binary_format_notes.md)|[Notes on FPGA & ARM](/doc/fpga_arm_notes.md)|
|[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)|[Notes on Magic cards](/doc/magic_cards_notes.md)|
|[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)|
@ -57,7 +57,7 @@ On the software side: quite a lot, see the [Changelog file](CHANGELOG.md).
This repo compiles nicely on
- Proxspace v3.x
- [latest release v3.6](https://github.com/Gator96100/ProxSpace/releases)
- [latest release v3.7](https://github.com/Gator96100/ProxSpace/releases)
- Windows/mingw environment with Qt5.6.1 & GCC 4.9
- Ubuntu 16.04 -> 20.04
- ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian

View file

@ -2,14 +2,14 @@ version: 3.0.1.{build}
image: Visual Studio 2019
clone_folder: C:\ProxSpace\pm3\proxmark
cache:
- C:\cache -> appveyor.yml
- C:\ps-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: C:\ProxSpace
proxspace_home_path: \ProxSpace\pm3
proxspace_cache_path: C:\cache
proxspace_cache_path: C:\ps-cache
wsl_git_path: C:\proxmark
APPVEYOR_SAVE_CACHE_ON_ERROR: true
@ -29,7 +29,6 @@ init:
$releasename+=$env:APPVEYOR_BUILD_VERSION + " [" + $env:APPVEYOR_REPO_COMMIT_SHORT + "]"
Write-Host "repository: $env:appveyor_repo_name branch:$env:APPVEYOR_REPO_BRANCH release: $releasename" -ForegroundColor Yellow
Add-AppveyorMessage -Message "[$env:APPVEYOR_REPO_COMMIT_SHORT]$env:appveyor_repo_name($env:APPVEYOR_REPO_BRANCH)" -Category Information -Details "repository: $env:appveyor_repo_name branch: $env:APPVEYOR_REPO_BRANCH release: $releasename"
@ -68,6 +67,7 @@ clone_script:
WSLExec "WSL install..." "sudo apt-get -y install --reinstall --no-install-recommends git ca-certificates build-essential pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev qtbase5-dev cmake 1>/dev/null"
WSLExec "WSL QT fix..." "sudo strip --remove-section=.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.so.5"
Add-AppveyorMessage -Message "WSL setup took $(([System.Environment]::TickCount-$WSLInstallTime) / 1000) sec" -Category Information
New-Item -ItemType "file" -Path "C:\WSL-Finished.txt" -Force | Out-Null
}
$env:PSInstallTime=[System.Environment]::TickCount
@ -154,8 +154,9 @@ install:
}
Start-Sleep -s 5
Receive-Job -Name WSLInstall
Receive-Job -Name WSLInstall -ErrorAction SilentlyContinue
}
#Receive-Job -Wait -Name PSInstall
}
Function GitClone($Text, $Folder) {
@ -175,7 +176,9 @@ install:
Write-Host "ProxSpace: move cache..." -NoNewLine
Move-Item -Path "$env:proxspace_cache_path" -Destination "$env:proxspace_path\msys2\var\cache" -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path "$env:proxspace_path\msys2\var\cache\" | Out-Null
Copy-Item -Path "$env:proxspace_cache_path\*" -Destination "$env:proxspace_path\msys2\var\cache\" -Force -Recurse -ErrorAction SilentlyContinue
Write-Host "[ OK ]" -ForegroundColor Gree
@ -212,6 +215,7 @@ build_script:
$WSLjob = Start-Job -Name WSLCompile -ScriptBlock {
Function ExecWSLCmd($Cmd) {
cd $env:wsl_git_path
wsl -- bash -c $Cmd
}
@ -231,11 +235,17 @@ build_script:
}
#WSL: wait for installation to finish
Receive-Job -Wait -Name WSLInstall
if(!(Test-Path "C:\WSL-Finished.txt")){
Write-Host "Waiting for WSL installation to finish..." -NoNewLine
while(!(Test-Path "C:\WSL-Finished.txt")) {
Start-Sleep -s 5
}
Remove-Item -Force "C:\WSL-Finished.txt" -ErrorAction SilentlyContinue
Write-Host "$Name [ OK ]" -ForegroundColor Green
}
#Windows Subsystem for Linux (WSL)
Write-Host "---------- WSL make ----------" -ForegroundColor Yellow
cd $env:wsl_git_path
$TestTime=[System.Environment]::TickCount
ExecWSLCmd "make clean;make V=1"
#some checks
@ -266,7 +276,9 @@ build_script:
Write-Host "ProxSpace: create new cache..." -NoNewLine
ExecMinGWCmd 'yes | pacman -Sc > /dev/null 2>&1'
cd $env:proxspace_path
./runme64.bat -c "yes | pacman -Sc > /dev/null 2>&1"
Remove-Item -Recurse -Force -Path "$env:proxspace_cache_path" -ErrorAction SilentlyContinue
@ -316,8 +328,9 @@ build_script:
ExecCheck "PS cmake Tests"
Receive-Job -Wait -Job $WSLjob
Receive-Job -Wait -Name WSLInstall -ErrorAction SilentlyContinue
Receive-Job -Wait -Job $WSLjob
test_script:
- ps: >-

View file

@ -147,14 +147,18 @@ void RunMod(void) {
int state = STATE_SEARCH;
DbpString("Scanning...");
int button_pressed = BUTTON_NO_CLICK;
for (;;) {
// Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000);
button_pressed = BUTTON_HELD(1000);
if (button_pressed != BUTTON_NO_CLICK || data_available())
break;
else if (state == STATE_SEARCH) {
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, true)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
SpinDelay(500);
continue;
} else {
if (card.sak == SAK && card.atqa[0] == ATQA0 && card.atqa[1] == ATQA1 && card.uidlen == 7) {
@ -245,6 +249,8 @@ void RunMod(void) {
state = STATE_SEARCH;
}
}
if (button_pressed == BUTTON_HOLD) //Holding down the button
break;
}
DbpString("exiting");

View file

@ -484,22 +484,18 @@ failtag:
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
SpinOff(50);
LED_A_ON();
uint8_t ticker = 0;
while (!iso14443a_select_card(cjuid, &p_card, &cjcuid, true, 0, true)) {
WDT_HIT();
ticker++;
if (ticker % 64 == 0) {
LED_A_INV();
}
if (BUTTON_HELD(10) == BUTTON_HOLD) {
WDT_HIT();
DbprintfEx(FLAG_NEWLINE, "\t\t\t[ READING FLASH ]");
ReadLastTagFromFlash();
goto readysim;
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(500);
LED_A_INV();
}
SpinOff(50);

View file

@ -125,7 +125,7 @@ static void download_instructions(uint8_t t) {
case ICE_STATE_FULLSIM: {
DbpString("The emulator memory was saved to SPIFFS");
DbpString("1. " _YELLOW_("mem spiffs dump o " HF_ICLASS_FULLSIM_MOD_BIN " f " HF_ICLASS_FULLSIM_MOD" e"));
DbpString("2. " _YELLOW_("hf iclass view f " HF_ICLASS_FULLSIM_MOD_BIN));
DbpString("2. " _YELLOW_("hf iclass view -f " HF_ICLASS_FULLSIM_MOD_BIN));
break;
}
case ICE_STATE_ATTACK: {

View file

@ -575,4 +575,5 @@ void RunMod(void) {
}
}
}
LEDsoff();
}

View file

@ -305,6 +305,8 @@ void RunMod(void) {
DbpString("\n"_YELLOW_("!!") "Waiting for a card reader...");
}
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
} else if (state == STATE_EMU) {
LED_A_OFF();
LED_C_ON();

View file

@ -54,7 +54,7 @@ void RunMod(void) {
for (;;) {
WDT_HIT();
// exit from Standalone Mode, send a usbcommand.
if (data_available()) return;
if (data_available()) break;
SpinDelay(300);
@ -72,7 +72,7 @@ void RunMod(void) {
for (;;) {
// exit from Standalone Mode, send a usbcommand.
if (data_available()) return;
if (data_available()) break;
if (BUTTON_PRESS()) {
if (cardRead[selected]) {
@ -89,6 +89,9 @@ void RunMod(void) {
}
if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
SpinDelay(500);
continue;
} else {
Dbprintf("Read UID:");
@ -220,7 +223,7 @@ void RunMod(void) {
DbpString("Playing");
for (; ;) {
// exit from Standalone Mode, send a usbcommand.
if (data_available()) return;
if (data_available()) break;
int button_pressed = BUTTON_HELD(1000);
if (button_pressed == BUTTON_NO_CLICK) { // No button action, proceed with sim
@ -277,4 +280,6 @@ void RunMod(void) {
LED(selected + 1, 0);
}
}
DbpString(_YELLOW_("[=]") "exiting");
LEDsoff();
}

View file

@ -68,6 +68,24 @@ extern uint32_t _stack_start, _stack_end;
struct common_area common_area __attribute__((section(".commonarea")));
static int button_status = BUTTON_NO_CLICK;
static bool allow_send_wtx = false;
static uint16_t tearoff_delay_us = 0;
static bool tearoff_enabled = false;
int tearoff_hook(void) {
if (tearoff_enabled) {
if (tearoff_delay_us == 0) {
Dbprintf(_RED_("No tear-off delay configured!"));
return PM3_SUCCESS; // SUCCESS = the hook didn't do anything
}
SpinDelayUsPrecision(tearoff_delay_us);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
tearoff_enabled = false;
Dbprintf(_YELLOW_("Tear-off triggered!"));
return PM3_ETEAROFF;
} else {
return PM3_SUCCESS; // SUCCESS = the hook didn't do anything
}
}
void send_wtx(uint16_t wtx) {
if (allow_send_wtx) {
@ -731,6 +749,24 @@ static void PacketReceived(PacketCommandNG *packet) {
reply_ng(CMD_SET_DBGMODE, PM3_SUCCESS, NULL, 0);
break;
}
case CMD_SET_TEAROFF: {
struct p {
uint16_t delay_us;
bool on;
bool off;
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
if (payload->on && payload->off)
reply_ng(CMD_SET_TEAROFF, PM3_EINVARG, NULL, 0);
if (payload->on)
tearoff_enabled = true;
if (payload->off)
tearoff_enabled = false;
if (payload->delay_us > 0)
tearoff_delay_us = payload->delay_us;
reply_ng(CMD_SET_TEAROFF, PM3_SUCCESS, NULL, 0);
break;
}
// always available
case CMD_HF_DROPFIELD: {
hf_field_off();
@ -827,7 +863,8 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_LF_HID_CLONE: {
CopyHIDtoT55x7(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes[0]);
lf_hidsim_t *payload = (lf_hidsim_t *)packet->data.asBytes;
CopyHIDtoT55x7(payload->hi2, payload->hi, payload->lo, payload->longFMT);
break;
}
case CMD_LF_IO_WATCH: {
@ -954,6 +991,16 @@ static void PacketReceived(PacketCommandNG *packet) {
EM4xWriteWord(payload->address, payload->data, payload->password, payload->usepwd);
break;
}
case CMD_LF_EM4X_PROTECTWORD: {
struct p {
uint32_t password;
uint32_t data;
uint8_t usepwd;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
EM4xProtectWord(payload->data, payload->password, payload->usepwd);
break;
}
case CMD_LF_AWID_WATCH: {
uint32_t high, low;
int res = lf_awid_watch(0, &high, &low);

View file

@ -16,6 +16,8 @@
extern int g_rsamples; // = 0;
extern uint8_t g_trigger;
int tearoff_hook(void);
// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV
#define MAX_ADC_HF_VOLTAGE 36300
// ADC Vref = 3300mV, (240k-10M):240k voltage divider, 140800 mV

View file

@ -134,11 +134,36 @@ static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ;
void printHf14aConfig(void) {
DbpString(_CYAN_("HF 14a config"));
Dbprintf("[a] Anticol override......%i: %s%s%s", hf14aconfig.forceanticol, (hf14aconfig.forceanticol == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forceanticol == 1) ? _RED_("Yes: Always do anticol") : "", (hf14aconfig.forceanticol == 2) ? _RED_("Yes: Always skip anticol") : "");
Dbprintf("[b] BCC override..........%i: %s%s%s", hf14aconfig.forcebcc, (hf14aconfig.forcebcc == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcebcc == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcebcc == 2) ? _RED_("Yes: Always use card BCC") : "");
Dbprintf("[2] CL2 override..........%i: %s%s%s", hf14aconfig.forcecl2, (hf14aconfig.forcecl2 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl2 == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcecl2 == 2) ? _RED_("Yes: Always skip CL2") : "");
Dbprintf("[3] CL3 override..........%i: %s%s%s", hf14aconfig.forcecl3, (hf14aconfig.forcecl3 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl3 == 1) ? _RED_("Yes: Always do CL3") : "", (hf14aconfig.forcecl3 == 2) ? _RED_("Yes: Always skip CL3") : "");
Dbprintf("[r] RATS override.........%i: %s%s%s", hf14aconfig.forcerats, (hf14aconfig.forcerats == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcerats == 1) ? _RED_("Yes: Always do RATS") : "", (hf14aconfig.forcerats == 2) ? _RED_("Yes: Always skip RATS") : "");
Dbprintf(" [a] Anticol override....%i %s%s%s",
hf14aconfig.forceanticol,
(hf14aconfig.forceanticol == 0) ? "( " _GREEN_("No") " ) follow standard " : "",
(hf14aconfig.forceanticol == 1) ? "( " _RED_("Yes") " ) always do anticol" : "",
(hf14aconfig.forceanticol == 2) ? "( " _RED_("Yes") " ) always skip anticol" : ""
);
Dbprintf(" [b] BCC override........%i %s%s%s",
hf14aconfig.forcebcc,
(hf14aconfig.forcebcc == 0) ? "( " _GREEN_("No") " ) follow standard" : "",
(hf14aconfig.forcebcc == 1) ? "( " _RED_("Yes") " ) always do CL2" : "",
(hf14aconfig.forcebcc == 2) ? "( " _RED_("Yes") " ) always use card BCC" : ""
);
Dbprintf(" [2] CL2 override........%i %s%s%s",
hf14aconfig.forcecl2,
(hf14aconfig.forcecl2 == 0) ? "( " _GREEN_("No") " ) follow standard" : "",
(hf14aconfig.forcecl2 == 1) ? "( " _RED_("Yes") " ) always do CL2" : "",
(hf14aconfig.forcecl2 == 2) ? "( " _RED_("Yes") " ) always skip CL2" : ""
);
Dbprintf(" [3] CL3 override........%i %s%s%s",
hf14aconfig.forcecl3,
(hf14aconfig.forcecl3 == 0) ? "( " _GREEN_("No") " ) follow standard" : "",
(hf14aconfig.forcecl3 == 1) ? "( " _RED_("Yes") " ) always do CL3" : "",
(hf14aconfig.forcecl3 == 2) ? "( " _RED_("Yes") " ) always skip CL3" : ""
);
Dbprintf(" [r] RATS override.......%i %s%s%s",
hf14aconfig.forcerats,
(hf14aconfig.forcerats == 0) ? "( " _GREEN_("No") " q follow standard " : "",
(hf14aconfig.forcerats == 1) ? "( " _RED_("Yes") " ) always do RATS" : "",
(hf14aconfig.forcerats == 2) ? "( " _RED_("Yes") " ) always skip RATS" : ""
);
}
/**

View file

@ -2369,6 +2369,7 @@ int copy_em410x_to_t55xx(uint8_t card, uint8_t clock, uint32_t id_hi, uint32_t i
#define FWD_CMD_LOGIN 0xC
#define FWD_CMD_WRITE 0xA
#define FWD_CMD_READ 0x9
#define FWD_CMD_PROTECT 0x3
#define FWD_CMD_DISABLE 0x5
static uint8_t forwardLink_data[64]; //array of forwarded bits
@ -2572,14 +2573,61 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
SendForward(len);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
StopTicks();
reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_ETEAROFF, NULL, 0);
} else {
// Wait 20ms for write to complete?
WaitMS(7);
// No, when write is denied, err preamble comes much sooner
//WaitUS(10820); // tPC+tWEE
DoPartialAcquisition(20, false, 6000, 1000);
DoPartialAcquisition(0, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0);
}
LEDsoff();
}
void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) {
StartTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
WaitMS(50);
LED_A_ON();
// clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false);
/* should we read answer from Logincommand?
*
* should receive
* 0000 1010 ok.
* 0000 0001 fail
**/
if (usepwd) EM4xLogin(pwd);
forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);
len += Prepare_Data(data & 0xFFFF, data >> 16);
SendForward(len);
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
StopTicks();
reply_ng(CMD_LF_EM4X_PROTECTWORD, PM3_ETEAROFF, NULL, 0);
} else {
// Wait 20ms for write to complete?
// No, when write is denied, err preamble comes much sooner
//WaitUS(13640); // tPC+tPR
DoPartialAcquisition(0, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
reply_ng(CMD_LF_EM4X_PROTECTWORD, PM3_SUCCESS, NULL, 0);
}
LEDsoff();
}

View file

@ -58,6 +58,7 @@ void TurnReadLFOn(uint32_t delay);
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd);
void Cotag(uint32_t arg0);
void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c);

View file

@ -2702,25 +2702,24 @@ void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain) {
uint8_t data_testwrite[4] = {0x00};
memcpy(data_fullwrite, datain, 4);
memcpy(data_testwrite, datain + 4, 4);
// optional authentication before?
if (DBGLEVEL >= DBG_ERROR) DbpString("Preparing OTP tear-off");
if (DBGLEVEL >= DBG_DEBUG) DbpString("Preparing OTP tear-off");
if (tearOffTime > 43000)
tearOffTime = 43000;
MifareUWriteBlock(blockNo, 0, data_fullwrite);
LEDsoff();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
set_tracing(true);
StartTicks();
// write cmd to send, include CRC
// 1b write, 1b block, 4b data, 2 crc
uint8_t cmd[] = {MIFARE_ULC_WRITE, blockNo, data_testwrite[0], data_testwrite[1], data_testwrite[2], data_testwrite[3], 0, 0};
MifareUWriteBlock(blockNo, 0, data_fullwrite);
AddCrc14A(cmd, sizeof(cmd) - 2);
if (DBGLEVEL >= DBG_ERROR) DbpString("Transmitting");
// anticollision / select card
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
@ -2732,11 +2731,10 @@ void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain) {
// Wait before cutting power. aka tear-off
LED_D_ON();
WaitUS(tearOffTime);
SpinDelayUsPrecision(tearOffTime);
if (DBGLEVEL >= DBG_DEBUG) Dbprintf(_YELLOW_("OTP tear-off triggered!"));
switch_off();
reply_ng(CMD_HF_MFU_OTP_TEAROFF, PM3_SUCCESS, NULL, 0);
StopTicks();
if (DBGLEVEL >= DBG_ERROR) DbpString("Done");
}

View file

@ -13,6 +13,31 @@
#include "proxmark3_arm.h"
#include "dbprint.h"
// timer counts in 666ns increments (32/48MHz), rounding applies
// WARNING: timer can't measure more than 43ms (666ns * 0xFFFF)
void SpinDelayUsPrecision(int us) {
int ticks = ((MCK / 1000000) * us + 16) >> 5;
// Borrow a PWM unit for my real-time clock
AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
// 48 MHz / 32 gives 1.5 Mhz
AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(5); // Channel Mode Register
AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register
AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xFFFF; // Channel Period Register
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
for (;;) {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
if (now == (uint16_t)(start + ticks))
return;
WDT_HIT();
}
}
// timer counts in 21.3us increments (1024/48MHz), rounding applies
// WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
void SpinDelayUs(int us) {

View file

@ -20,6 +20,7 @@
void SpinDelay(int ms);
void SpinDelayUs(int us);
void SpinDelayUsPrecision(int us); // precision 0.6us , running for 43ms before
void StartTickCount(void);
uint32_t RAMFUNC GetTickCount(void);

View file

@ -248,7 +248,7 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/cmdlfcotag.c
${PM3_ROOT}/client/src/cmdlfem4x.c
${PM3_ROOT}/client/src/cmdlfem4x50.c
${PM3_ROOT}/client/src/cmdlffdx.c
${PM3_ROOT}/client/src/cmdlffdxb.c
${PM3_ROOT}/client/src/cmdlfgallagher.c
${PM3_ROOT}/client/src/cmdlfguard.c
${PM3_ROOT}/client/src/cmdlfhid.c

View file

@ -309,6 +309,7 @@ ifeq ($(QT_FOUND),1)
endif
endif
LDFLAGS ?= $(DEFLDFLAGS)
PM3LDFLAGS = $(LDFLAGS)
ifeq ($(platform),Darwin)
PM3LDFLAGS += -framework Foundation -framework AppKit
@ -442,7 +443,7 @@ SRCS = aidsearch.c \
cmdlfcotag.c \
cmdlfem4x.c \
cmdlfem4x50.c \
cmdlffdx.c \
cmdlffdxb.c \
cmdlfguard.c \
cmdlfgallagher.c \
cmdlfhid.c \

View file

@ -127,7 +127,7 @@ add_library(pm3rrg_rdv4 SHARED
${PM3_ROOT}/client/src/cmdlfcotag.c
${PM3_ROOT}/client/src/cmdlfem4x.c
${PM3_ROOT}/client/src/cmdlfem4x50.c
${PM3_ROOT}/client/src/cmdlffdx.c
${PM3_ROOT}/client/src/cmdlffdxb.c
${PM3_ROOT}/client/src/cmdlfgallagher.c
${PM3_ROOT}/client/src/cmdlfguard.c
${PM3_ROOT}/client/src/cmdlfhid.c

View file

@ -740,8 +740,12 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap) {
case 'b':
if (root && !json_is_boolean(root)) {
set_error(s, "<validation>", json_error_wrong_type, "Expected true or false, got %s",
type_name(root));
set_error(s,
"<validation>",
json_error_wrong_type,
"Expected true or false, got %s",
type_name(root)
);
return -1;
}

View file

@ -167,8 +167,9 @@ int reveng_main(int argc, char *argv[]) {
pkchop(&model.spoly);
width = plen(model.spoly);
rflags |= R_HAVEP;
if (c == 'P')
if (c == 'P') {
prcp(&model.spoly);
}
mnovel(&model);
break;
case 'l': /* l little-endian input and output */
@ -332,6 +333,7 @@ ipqx:
mbynum(&model, --args);
ufound(&model);
} while (args);
mfree(&model);
break;
case 'd': /* d dump CRC model */
/* maybe we don't want to do this:
@ -387,6 +389,10 @@ ipqx:
apolys = calloc(args * sizeof(poly_t), sizeof(char));
if (!apolys) {
uerror("cannot allocate memory for argument list");
pfree(&model.spoly);
pfree(&model.init);
pfree(&model.xorout);
mfree(&model);
return 0;
}
@ -421,17 +427,21 @@ ipqx:
continue;
if (rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout))
continue;
apoly = pclone(pset.xorout);
if (pset.flags & P_REFOUT)
if (pset.flags & P_REFOUT) {
prev(&apoly);
}
for (qptr = apolys; qptr < pptr; ++qptr) {
crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0);
if (ptst(crc)) {
pfree(&crc);
break;
} else
} else {
pfree(&crc);
}
}
pfree(&apoly);
if (qptr == pptr) {
/* the selected model solved all arguments */
@ -444,14 +454,19 @@ ipqx:
/* toggle refIn/refOut and reflect arguments */
if (~rflags & R_HAVERI) {
model.flags ^= P_REFIN | P_REFOUT;
for (qptr = apolys; qptr < pptr; ++qptr)
for (qptr = apolys; qptr < pptr; ++qptr) {
prevch(qptr, ibperhx);
}
}
} while (~rflags & R_HAVERI && ++pass < 2);
}
if (uflags & C_RESULT) {
for (qptr = apolys; qptr < pptr; ++qptr)
for (qptr = apolys; qptr < pptr; ++qptr) {
pfree(qptr);
}
free(apolys);
mfree(&model);
return 1;
//exit(EXIT_SUCCESS);
}
@ -467,8 +482,10 @@ ipqx:
pass = 0;
do {
mptr = candmods = reveng(&model, qpoly, rflags, args, apolys);
if (mptr && plen(mptr->spoly))
if (mptr && plen(mptr->spoly)) {
uflags |= C_RESULT;
}
while (mptr && plen(mptr->spoly)) {
/* results were printed by the callback
* string = mtostr(mptr);
@ -478,26 +495,31 @@ ipqx:
mfree(mptr++);
}
free(candmods);
if (~rflags & R_HAVERI) {
model.flags ^= P_REFIN | P_REFOUT;
for (qptr = apolys; qptr < pptr; ++qptr)
for (qptr = apolys; qptr < pptr; ++qptr) {
prevch(qptr, ibperhx);
}
}
} while (~rflags & R_HAVERI && ++pass < 2);
for (qptr = apolys; qptr < pptr; ++qptr)
for (qptr = apolys; qptr < pptr; ++qptr) {
pfree(qptr);
}
free(apolys);
if (~uflags & C_RESULT)
uerror("no models found");
break;
default: /* no mode specified */
fprintf(stderr, "%s: no mode switch specified. Use %s -h for help.\n", myname, myname);
return 0;
//exit(EXIT_FAILURE);
}
return 1;
//exit(EXIT_SUCCESS);
}
void

View file

@ -0,0 +1,176 @@
local getopt = require('getopt')
local ansicolors = require('ansicolors')
copyright = 'Iceman'
author = 'Iceman'
version = 'v0.9.9'
desc = [[
This is scripts loops though a tear attack and reads expected value.
]]
example = [[
1. script run tearoff -n 2 -s 200 -e 400 -a 5
]]
usage = [[
script run tearoff [-h] [-n <steps us>] [-a <addr>] [-p <pwd>] [-s <start us>] [-e <end us>] [-r <read>] [-w <write>]
]]
arguments = [[
-h This help
-n <steps us> steps in milliseconds for each tearoff
-a <addr> address to target on card
-p <pwd> (optional) use a password
-s <delay us> initial start delay
-e <delay us> end delay, must be larger than start delay
-r <read value> 4 hex bytes value to be read
-w <write value> 4 hex bytes value to be written
end
]]
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR:', err)
core.clearCommandBuffer()
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
local function main(args)
--[[
Basically do the following,
1. hw tear
2. lf em 4x05_write
3. lf em 4x05_read
The first two commands doesn't need a feedback from the system, so going with core.console commands.
Since the read needs demodulation of signal I opted to add that function from cmdlfem4x.c to the core lua scripting
core.em4x05_read(addr, password)
--]]
local n, addr, password, sd, ed, wr_value, rd_value
for o, a in getopt.getopt(args, 'he:s:a:p:n:r:w:') do
if o == 'h' then return help() end
if o == 'n' then n = a end
if o == 'a' then addr = a end
if o == 'p' then password = a end
if o == 'e' then ed = tonumber(a) end
if o == 's' then sd = tonumber(a) end
if o == 'w' then wr_value = a end
if o == 'r' then rd_value = a end
end
rd_value = rd_value or 'FFFFFFFF'
wr_value = wr_value or 'FFFFFFFF'
addr = addr or 5
password = password or ''
n = n or 2
sd = sd or 2000
ed = ed or 2100
if #password ~= 8 then
password = ''
end
if #wr_value ~= 8 then
wr_value = 'FFFFFFFF'
end
if #rd_value ~= 8 then
rd_value = 'FFFFFFFF'
end
if sd > ed then
return oops('start delay can\'t be larger than end delay', sd, ed)
end
print('Starting EM4x05 tear off')
print('target addr', addr)
if password then
print('target pwd', password)
end
print('target stepping', n)
print('target delay', sd ,ed)
print('read value', rd_value)
print('write value', wr_value)
local res_tear = 0
local res_nowrite = 0
local set_tearoff_delay = 'hw tearoff --delay %d'
local enable_tearoff = 'hw tearoff --on'
local wr_template = 'lf em 4x05_write %s %s %s'
-- init addr to value
core.console(wr_template:format(addr, wr_value, password))
if sd == ed then
ed = n
n = 0
end
for step = sd, ed, n do
io.flush()
if core.kbd_enter_pressed() then
print("aborted by user")
break
end
core.clearCommandBuffer()
-- reset addr to known value, if not locked into.
if n ~= 0 then
c = wr_template:format(addr, wr_value, password)
core.console(c)
end
local c = set_tearoff_delay:format(step)
core.console(c);
core.console(enable_tearoff)
c = wr_template:format(addr, wr_value, password)
core.console(c)
local word, err = core.em4x05_read(addr, password)
if err then
return oops(err)
end
local wordstr = ('%08X'):format(word)
if wordstr ~= wr_value then
if wordstr ~= rd_value then
print((ansicolors.red..'TEAR OFF occurred:'..ansicolors.reset..' %08X'):format(word))
res_tear = res_tear + 1
else
print((ansicolors.cyan..'TEAR OFF occurred:'..ansicolors.reset..' %08X'):format(word))
res_nowrite = res_nowrite + 1
end
else
print((ansicolors.green..'Good write occurred:'..ansicolors.reset..' %08X'):format(word))
end
end
end
--[[
In the future, we may implement so that scripts are invoked directly
into a 'main' function, instead of being executed blindly. For future
compatibility, I have done so, but I invoke my main from here.
--]]
main(args)

View file

@ -0,0 +1,326 @@
local getopt = require('getopt')
local ansicolors = require('ansicolors')
copyright = 'Iceman'
author = [[
'Author Iceman
CoAuthor Doegox
]]
version = 'v1.0.1'
desc = [[
This is scripts loops though a tear attack and reads expected value.
]]
example = [[
Full automatic, with password:
script run lf_em_tearoff_protect -p 50524F58
Manual fix increment over specified range:
script run lf_em_tearoff_protect -n 2 -s 200 -e 400
Trying repeatedly for a fixed timing, forever or till success:
script run lf_em_tearoff_protect -s 400 -e 400
Tips:
Use a low Q antenna
Move card somehow away from the antenna to a position where it still works
]]
usage = [[
script run lf_em_tearoff_protect [-h] [-n <steps us>] [-p <pwd>] [-s <start us>] [-e <end us>]
]]
arguments = [[
-h This help
-n <steps us> steps in milliseconds for each tear-off
-p <pwd> (optional) use a password
-s <delay us> initial start delay
-e <delay us> end delay, must be larger or equal to start delay
end
]]
local set_tearoff_delay = 'hw tearoff -s --on --delay %d'
local wr_template = 'lf em 4x05_write %s %s %s'
---
-- This is only meant to be used when errors occur
local function oops(err)
print('ERROR:', err)
core.clearCommandBuffer()
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
local function exit_msg()
print('')
print('================= '..ansicolors.green..'verify with'..ansicolors.reset..' =================')
print(' lf em 4x05_dump')
print('===============================================')
return nil
end
local function reset(wr_value, password)
print('[=] '..ansicolors.red..'resetting the active lock block'..ansicolors.reset)
core.console(wr_template:format(99, wr_value, password))
end
local function main(args)
--[[
Basically it does the following,
1. hw tear
2. lf em 4x05_write
3. lf em 4x05_read
The first two commands dont need a feedback from the system, so going with core.console commands.
Since the read needs demodulation of signal I opted to add that function from cmdlfem4x.c to the core lua scripting
core.em4x05_read(addr, password)
--]]
local n, password, sd, ed
for o, a in getopt.getopt(args, 'he:s:p:n:') do
if o == 'h' then return help() end
if o == 'n' then n = tonumber(a) end
if o == 'p' then password = a end
if o == 'e' then ed = tonumber(a) end
if o == 's' then sd = tonumber(a) end
end
password = password or ''
if #password ~= 8 then
password = ''
end
local word14, err14 = core.em4x05_read(14, password)
if err14 then
return oops(err14)
end
local word15, err15 = core.em4x05_read(15, password)
if err15 then
return oops(err15)
end
local bit15 = bit.band(0x00008000, word15)
if bit15 == 0x00008000 then
rd_value = ('%08X'):format(word15)
reset(wr_value, password)
else
rd_value = ('%08X'):format(word14)
end
if rd_value == '00008000' then
print('Tag already fully unlocked, nothing to do')
return nil
end
local wr_value = '00000000'
local auto = false
if n == nil then
auto = true
sd = sd or 2000
ed = ed or 6000
n = (ed - sd) / 2
else
if sd == nil or ed == nil then
return oops('start and stop delays need to be defined')
end
if sd > ed then
return oops('start delay can\'t be larger than end delay', sd, ed)
end
end
print('==========================================')
print('Starting EM4x05 tear-off : target PROTECT')
if password ~= '' then
print('target pwd', password)
end
if auto then
print('automatic mode', 'enabled')
end
print('target stepping', n)
print('target delay', sd ,ed)
print('read value', rd_value)
print('write value', wr_value)
print('==========================================')
local res_tear = 0
local res_nowrite = 0
-- fix at one specific delay
if sd == ed then
n = 0
end
local tries = 0
local soon = 0
local late = 0
while sd <= ed do
if auto and n < 1 then -- n is a float
print('[!] Reached n < 1 => '..ansicolors.yellow..'disabling automatic mode'..ansicolors.reset)
ed = sd
auto = false
n = 0
end
if not auto then
sd = sd + n
end
if (tries >= 5) and (n == 0) and (soon ~= late) then
if soon > late then
print(('[!] Tried %d times, soon:%i late:%i => '):format(tries, soon, late)..ansicolors.yellow..'adjusting delay by +1 us'..ansicolors.reset)
sd = sd + 1
ed = ed + 1
else
print(('[!] Tried %d times, soon:%i late:%i => '):format(tries, soon, late)..ansicolors.yellow..'adjusting delay by -1 us'..ansicolors.reset)
sd = sd - 1
ed = ed - 1
end
tries = 0
soon = 0
late = 0
end
io.flush()
if core.kbd_enter_pressed() then
print("aborted by user")
break
end
core.clearCommandBuffer()
local c = set_tearoff_delay:format(sd)
core.console(c);
c = wr_template:format(99, wr_value, password)
core.console(c)
word14, err14 = core.em4x05_read(14, password)
if err14 then
return oops(err14)
end
local wordstr14 = ('%08X'):format(word14)
word15, err15 = core.em4x05_read(15, password)
if err15 then
return oops(err15)
end
local wordstr15 = ('%08X'):format(word15)
print(('[=] ref:'..rd_value..' 14:%08X 15:%08X '):format(word14, word15))
if wordstr14 == rd_value and wordstr15 == '00000000' then
print('[=] Status: Nothing happened => '..ansicolors.green..'tearing too soon'..ansicolors.reset)
if auto then
sd = sd + n
n = n / 2
print(('[+] Adjusting params: n=%i sd=%i ed=%i'):format(n, sd, ed))
else
soon = soon + 1
end
else
if wordstr15 == rd_value then
if wordstr14 == '00000000' then
print('[=] Status: Protect succeeded => '..ansicolors.green..'tearing too late'..ansicolors.reset)
else
if wordstr14 == rd_value then
print('[=] Status: 15 ok, 14 not yet erased => '..ansicolors.green..'tearing too late'..ansicolors.reset)
else
print('[=] Status: 15 ok, 14 partially erased => '..ansicolors.green..'tearing too late'..ansicolors.reset)
end
end
reset(wr_value, password)
-- it could still happen that a bitflip got committed, let's check...
local word14b, err14b = core.em4x05_read(14, password)
if err14b then
return oops(err14b)
end
local wordstr14b = ('%08X'):format(word14b)
if (wordstr14b == '00000000') then
reset(wr_value, password)
end
if (wordstr14b ~= rd_value) then
local word15b, err15b = core.em4x05_read(15, password)
if err15b then
return oops(err15b)
end
print(('[=] Status: new definitive value! => '..ansicolors.red..'SUCCESS: '..ansicolors.reset..'14: '..ansicolors.cyan..'%08X'..ansicolors.reset..' 15: %08X'):format(word14b, word15b))
return exit_msg()
end
if auto then
ed = sd
sd = sd - n
n = n / 2
print(('[+] Adjusting params: n=%i sd=%i ed=%i'):format(n, sd, ed))
else
late = late + 1
end
else
bit15 = bit.band(0x00008000, word15)
if bit15 == 0x00008000 then
print(('[=] Status: 15 bitflipped and active => '..ansicolors.red..'SUCCESS?: '..ansicolors.reset..'14: %08X 15: '..ansicolors.cyan..'%08X'..ansicolors.reset):format(word14, word15))
print('[+] Committing results...')
reset(wr_value, password)
local word14b, err14b = core.em4x05_read(14, password)
if err14b then
return oops(err14b)
end
local wordstr14b = ('%08X'):format(word14b)
local word15b, err15b = core.em4x05_read(15, password)
if err15b then
return oops(err15b)
end
local wordstr15b = ('%08X'):format(word15b)
print(('[=] ref:'..rd_value..' 14:%08X 15:%08X '):format(word14b, word15b))
bit15 = bit.band(0x00008000, word14b)
if bit15 == 0x00008000 then
if (wordstr14b == wordstr15) then
print(('[=] Status: confirmed => '..ansicolors.red..'SUCCESS: '..ansicolors.reset..'14: '..ansicolors.cyan..'%08X'..ansicolors.reset..' 15: %08X'):format(word14b, word15b))
return exit_msg()
end
if (wordstr14b ~= rd_value) then
print(('[=] Status: new definitive value! => '..ansicolors.red..'SUCCESS: '..ansicolors.reset..'14: '..ansicolors.cyan..'%08X'..ansicolors.reset..' 15: %08X'):format(word14b, word15b))
return exit_msg()
end
print(('[=] Status: failed to commit bitflip => '..ansicolors.red..'FAIL: '..ansicolors.reset..'14: %08X 15: %08X'):format(word14b, word15b))
else
print(('[=] Status: failed to commit => '..ansicolors.red..'FAIL: '..ansicolors.reset..'14: %08X 15: %08X'):format(word14b, word15b))
end
else
print(('[=] Status: 15 bitflipped but inactive => '..ansicolors.yellow..'PROMISING: '..ansicolors.reset..'14: %08X 15: '..ansicolors.cyan..'%08X'..ansicolors.reset):format(word14, word15))
end
if auto then
n = 0
ed = sd
else
tries = 0
soon = 0
late = 0
end
end
end
if not auto then
tries = tries + 1
end
end
end
--[[
In the future, we may implement so that scripts are invoked directly
into a 'main' function, instead of being executed blindly. For future
compatibility, I have done so, but I invoke my main from here.
--]]
main(args)

View file

@ -192,7 +192,7 @@ local function main(args)
print('Press enter to program card '..cardnum..':'..facility..' (hex: '..card..')')
--This would be better with 'press Enter', but we'll take what we can get.
io.read()
core.console( ('lf hid clone %s'):format(card) )
core.console( ('lf hid clone -r %s'):format(card) )
end
end

View file

@ -18,7 +18,7 @@ desc = [[
\ / \ /
`---' `---'
*SUPPORTED TAGS: pyramid, awid, fdx, jablotron, noralsy, presco, visa2000, 14a, hid
*SUPPORTED TAGS: pyramid, awid, fdxb, jablotron, noralsy, presco, visa2000, 14a, hid
This script uses the Proxmark3 implementations of simulation to bruteforce given ranges of id.
It uses both LF and HF simulations.
@ -42,7 +42,7 @@ arguments = [[
-r *see below RFID Tag: the RFID tag to emulate
pyramid
awid
fdx
fdxb
jablotron
noralsy
presco
@ -180,8 +180,8 @@ local function main(args)
consolecommand = 'lf awid sim'
rfidtagname = 'AWID'
facilityrequired = 1
elseif rfidtag == 'fdx' then -- I'm not sure why you would need to bruteforce this ¯\_(ツ)_/¯
consolecommand = 'lf fdx sim'
elseif rfidtag == 'fdxb' then -- I'm not sure why you would need to bruteforce this ¯\_(ツ)_/¯
consolecommand = 'lf fdxb sim'
rfidtagname = 'FDX-B'
facilityrequired = 1
elseif rfidtag == 'jablotron' then
@ -214,7 +214,7 @@ local function main(args)
end
facilityrequired = 0 -- Disable the FC required check, as we used it for type instead of FC
elseif rfidtag == 'hid' then
consolecommand = 'lf hid sim'
consolecommand = 'lf hid sim -r'
rfidtagname = 'HID'
facilityrequired = 1
else -- Display error and exit out if bad RFID tag was supplied

View file

@ -77,7 +77,7 @@ local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
local cmdDataLoad = 'data load %s';
local cmdDataLoad = 'data load -f %s';
local cwd = core.cwd();
local tracesEM = "find '"..cwd.."/traces/ ' -iname 'em*.pm3' -type f"

View file

@ -25,6 +25,7 @@
#include "reveng.h"
#include "ui.h"
#include "util.h"
#include "pm3_cmd.h"
#define MAX_ARGS 20
@ -253,7 +254,6 @@ int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *res
int ibperhx = 8, obperhx = 8;
// int rflags = 0; // search flags
int c;
poly_t apoly, crc;
char *string;
@ -265,7 +265,7 @@ int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *res
SETBMP();
//set model
c = mbynam(&model, inModel);
int c = mbynam(&model, inModel);
if (!c) {
PrintAndLogEx(ERR, "error: preset model '%s' not found. Use reveng -D to list presets. [%d]", inModel, c);
return 0;
@ -405,7 +405,7 @@ static int CmdrevengSearch(const char *Cmd) {
#define NMODELS 106
char inHexStr[100] = {0x00};
char inHexStr[256] = {0x00};
int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr));
if (dataLen < 4) return 0;
@ -418,7 +418,12 @@ static int CmdrevengSearch(const char *Cmd) {
char revResult[30];
int ans = GetModels(Models, &count, width);
bool found = false;
if (!ans) return 0;
if (!ans) {
for (int i = 0; i < count; i++) {
free(Models[i]);
}
return 0;
}
// try each model and get result
for (int i = 0; i < count; i++) {
@ -429,8 +434,10 @@ static int CmdrevengSearch(const char *Cmd) {
// round up to # of characters in this model's crc
uint8_t crcChars = ((width[i] + 7) / 8) * 2;
// can't test a model that has more crc digits than our data
if (crcChars >= dataLen)
if (crcChars >= dataLen) {
free(Models[i]);
continue;
}
PrintAndLogEx(DEBUG
, "DEBUG: dataLen %d, crcChars %u, width[i] %u"
@ -439,8 +446,10 @@ static int CmdrevengSearch(const char *Cmd) {
, width[i]
);
if (crcChars == 0)
if (crcChars == 0) {
free(Models[i]);
continue;
}
memset(result, 0, 30);
char *inCRC = calloc(crcChars + 1, sizeof(char));
@ -492,26 +501,29 @@ static int CmdrevengSearch(const char *Cmd) {
free(Models[i]);
}
if (!found) PrintAndLogEx(FAILED, "\nno matches found\n");
return 1;
if (found == false)
PrintAndLogEx(FAILED, "\nno matches found\n");
return PM3_SUCCESS;
}
int CmdCrc(const char *Cmd) {
char name[] = {"reveng "};
char Cmd2[100 + 7];
memcpy(Cmd2, name, 7);
memcpy(Cmd2 + 7, Cmd, 100);
char c[100 + 7];
snprintf(c, sizeof(c), "reveng ");
snprintf(c + strlen(c), sizeof(c) - strlen(c), Cmd, strlen(Cmd));
char *argv[MAX_ARGS];
int argc = split(Cmd2, argv);
int argc = split(c, argv);
if (argc == 3 && memcmp(argv[1], "-g", 2) == 0) {
CmdrevengSearch(argv[2]);
} else {
reveng_main(argc, argv);
}
for (int i = 0; i < argc; ++i) {
free(argv[i]);
}
return 0;
return PM3_SUCCESS;
}

View file

@ -27,31 +27,17 @@
#include "fileutils.h" // searchFile
#include "mifare/ndef.h"
#include "cliparser.h"
#include "cmdlft55xx.h" // print...
uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
size_t DemodBufferLen = 0;
size_t g_DemodStartIdx = 0;
int32_t g_DemodStartIdx = 0;
int g_DemodClock = 0;
static int CmdHelp(const char *Cmd);
static int usage_data_save(void) {
PrintAndLogEx(NORMAL, "Save trace from graph window , i.e. the GraphBuffer");
PrintAndLogEx(NORMAL, "This is a text file with number -127 to 127. With the option `w` you can save it as wave file");
PrintAndLogEx(NORMAL, "Filename should be without file extension");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: data save [h] [w] [f <filename w/o ext>]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " w save as wave format (.wav)");
PrintAndLogEx(NORMAL, " f <filename> save file name");
PrintAndLogEx(NORMAL, "Samples:");
PrintAndLogEx(NORMAL, " data save f mytrace - save graphbuffer to file");
PrintAndLogEx(NORMAL, " data save f mytrace w - save graphbuffer to wave file");
return PM3_SUCCESS;
}
static int usage_data_printdemodbuf(void) {
PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o <offset> l <length>");
PrintAndLogEx(NORMAL, "Usage: data print x o <offset> l <length>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " i invert Demodbuffer before printing");
@ -236,15 +222,6 @@ static int usage_data_autocorr(void) {
PrintAndLogEx(NORMAL, " g save back to GraphBuffer (overwrite)");
return PM3_SUCCESS;
}
static int usage_data_undecimate(void) {
PrintAndLogEx(NORMAL, "Usage: data undec [factor]");
PrintAndLogEx(NORMAL, "This function performs un-decimation, by repeating each sample N times");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " factor The number of times to repeat each sample.[default:2]");
PrintAndLogEx(NORMAL, "Example: 'data undec 3'");
return PM3_SUCCESS;
}
static int usage_data_detectclock(void) {
PrintAndLogEx(NORMAL, "Usage: data detectclock [modulation] <clock>");
PrintAndLogEx(NORMAL, " [modulation as char], specify the modulation type you want to detect the clock of");
@ -269,7 +246,7 @@ static int usage_data_bin2hex(void) {
}
static int usage_data_buffclear(void) {
PrintAndLogEx(NORMAL, "This function clears the bigbuff on deviceside");
PrintAndLogEx(NORMAL, "Usage: data buffclear [h]");
PrintAndLogEx(NORMAL, "Usage: data clear [h]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
return PM3_SUCCESS;
@ -544,6 +521,7 @@ static int CmdConvertBitStream(const char *Cmd) {
//emSearch will auto search for EM410x format in bitstream
//askType switches decode: ask/raw = 0, ask/manchester = 1
int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) {
PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) clk %i invert %i maxErr %i maxLen %zu amplify %i verbose %i emSearch %i askType %i ", clk, invert, maxErr, maxLen, amplify, verbose, emSearch, askType);
uint8_t askamp = 0;
if (!maxLen) maxLen = pm3_capabilities.bigbuf_size;
@ -638,28 +616,37 @@ int ASKDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool
//attempts to demodulate ask while decoding manchester
//prints binary found and saves in graphbuffer for further commands
static int Cmdaskmandemod(const char *Cmd) {
size_t slen = strlen(Cmd);
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) > 45 || cmdp == 'h') return usage_data_rawdemod_am();
bool st = false;
if (slen > 45 || cmdp == 'h') return usage_data_rawdemod_am();
bool st = false, amplify = false;
int clk = 0, invert = 0, maxErr = 100;
size_t maxLen = 0;
if (slen) {
if (Cmd[0] == 's') {
st = true;
Cmd++;
} else if (Cmd[1] == 's') {
} else if (slen > 1 && Cmd[1] == 's') {
st = true;
Cmd += 2;
}
int clk = 0;
int invert = 0;
int maxErr = 100;
size_t maxLen = 0;
bool amplify = false;
char amp = tolower(param_getchar(Cmd, 0));
sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &amp);
amplify = amp == 'a';
amplify = (amp == 'a');
}
if (clk == 1) {
invert = 1;
clk = 0;
}
if (invert != 0 && invert != 1) {
PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert);
return PM3_EINVARG;
@ -998,12 +985,29 @@ static int CmdBuffClear(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdDec(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
for (size_t i = 0; i < (GraphTraceLen / 2); ++i)
GraphBuffer[i] = GraphBuffer[i * 2];
GraphTraceLen /= 2;
PrintAndLogEx(NORMAL, "decimated by 2");
static int CmdDecimate(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "data decimate",
"Performs decimation, by reducing samples N times in the grapbuf. Good for PSK\n",
"data decimate\n"
"data decimate 4"
);
void *argtable[] = {
arg_param_begin,
arg_int0(NULL, NULL, "<dec>", "factor to reduce sample set (default 2)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int n = arg_get_int_def(ctx, 1, 2);
CLIParserFree(ctx);
for (size_t i = 0; i < (GraphTraceLen / n); ++i)
GraphBuffer[i] = GraphBuffer[i * n];
GraphTraceLen /= n;
PrintAndLogEx(SUCCESS, "decimated by " _GREEN_("%u"), n);
RepaintGraphWindow();
return PM3_SUCCESS;
}
@ -1014,19 +1018,34 @@ static int CmdDec(const char *Cmd) {
* @param Cmd
* @return
*/
static int CmdUndec(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_data_undecimate();
static int CmdUndecimate(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "data undecimate",
"Performs un-decimation, by repeating each sample N times in the graphbuf",
"data undecimate\n"
"data undecimate 4\n"
);
uint8_t factor = param_get8ex(Cmd, 0, 2, 10);
void *argtable[] = {
arg_param_begin,
arg_int0(NULL, NULL, "<dec>", "factor to repeat each sample (default 2)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int factor = arg_get_int_def(ctx, 1, 2);
CLIParserFree(ctx);
//We have memory, don't we?
int swap[MAX_GRAPH_TRACE_LEN] = {0};
uint32_t g_index = 0, s_index = 0;
while (g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN) {
int count = 0;
for (count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++)
swap[s_index + count] = GraphBuffer[g_index];
for (count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++) {
swap[s_index + count] = (
(double)(factor - count) / (factor - 1)) * GraphBuffer[g_index] +
((double)count / factor) * GraphBuffer[g_index + 1]
;
}
s_index += count;
g_index++;
}
@ -1437,7 +1456,7 @@ void setClockGrid(uint32_t clk, int offset) {
}
int CmdGrid(const char *Cmd) {
sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY);
sscanf(Cmd, "%lf %lf", &PlotGridX, &PlotGridY);
PlotGridXdefault = PlotGridX;
PlotGridYdefault = PlotGridY;
RepaintGraphWindow();
@ -1675,6 +1694,48 @@ int CmdTuneSamples(const char *Cmd) {
if (package->peak_v > NON_VOLTAGE && package->peak_f > 0)
PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (package->peak_v * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(package->peak_f));
const double vdd_rdv4 = 9000;
const double vdd_other = 5400; // Empirical measures in mV
double vdd = IfPm3Rdv4Fw() ? vdd_rdv4 : vdd_other;
if (package->peak_v > NON_VOLTAGE && package->peak_f > 0) {
// Q measure with Q=f/delta_f
double v_3db_scaled = (double)(package->peak_v * 0.707) / 512; // /512 == >>9
uint32_t s2 = 0, s4 = 0;
for (int i = 1; i < 256; i++) {
if ((s2 == 0) && (package->results[i] > v_3db_scaled)) {
s2 = i;
}
if ((s2 != 0) && (package->results[i] < v_3db_scaled)) {
s4 = i;
break;
}
}
double lfq1 = 0;
if (s4 != 0) { // we got all our points of interest
double a = package->results[s2 - 1];
double b = package->results[s2];
double f1 = LF_DIV2FREQ(s2 - 1 + (v_3db_scaled - a) / (b - a));
double c = package->results[s4 - 1];
double d = package->results[s4];
double f2 = LF_DIV2FREQ(s4 - 1 + (c - v_3db_scaled) / (c - d));
lfq1 = LF_DIV2FREQ(package->peak_f) / (f1 - f2);
PrintAndLogEx(SUCCESS, "Approx. Q factor (*): %.1lf by frequency bandwidth measurement", lfq1);
}
// Q measure with Vlr=Q*(2*Vdd/pi)
double lfq2 = (double)package->peak_v * 3.14 / 2 / vdd;
PrintAndLogEx(SUCCESS, "Approx. Q factor (*): %.1lf by peak voltage measurement", lfq2);
// cross-check results
if (lfq1 > 3) {
double approx_vdd = (double)package->peak_v * 3.14 / 2 / lfq1;
if ((approx_vdd > (vdd_rdv4 + vdd_other) / 2) && (! IfPm3Rdv4Fw()))
PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_OTHER firmware on a RDV4") ", please check your setup");
if ((approx_vdd < (vdd_rdv4 + vdd_other) / 2) && (IfPm3Rdv4Fw()))
PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_RDV4 firmware on a non-RDV4") ", please check your setup");
}
}
char judgement[20];
memset(judgement, 0, sizeof(judgement));
// LF evaluation
@ -1694,6 +1755,11 @@ int CmdTuneSamples(const char *Cmd) {
memset(judgement, 0, sizeof(judgement));
if (package->v_hf >= HF_UNUSABLE_V) {
// Q measure with Vlr=Q*(2*Vdd/pi)
double hfq = (double)package->v_hf * 3.14 / 2 / vdd;
PrintAndLogEx(SUCCESS, "Approx. Q factor (*): %.1lf by peak voltage measurement", hfq);
}
if (package->v_hf < HF_UNUSABLE_V)
sprintf(judgement, _RED_("UNUSABLE"));
else if (package->v_hf < HF_MARGINAL_V)
@ -1702,6 +1768,7 @@ int CmdTuneSamples(const char *Cmd) {
sprintf(judgement, _GREEN_("OK"));
PrintAndLogEx((package->v_hf < HF_UNUSABLE_V) ? WARNING : SUCCESS, "HF antenna is %s", judgement);
PrintAndLogEx(NORMAL, "\n(*) Q factor must be measured without tag on the antenna");
// graph LF measurements
// even here, these values has 3% error.
@ -1712,9 +1779,11 @@ int CmdTuneSamples(const char *Cmd) {
}
if (test1 > 0) {
PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor %d is %.2f kHz, %d is %.2f kHz.\n\n",
PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor %d (blue) is %.2f kHz, %d (red) is %.2f kHz.\n\n",
LF_DIVISOR_134, LF_DIV2FREQ(LF_DIVISOR_134), LF_DIVISOR_125, LF_DIV2FREQ(LF_DIVISOR_125));
GraphTraceLen = 256;
CursorCPos = LF_DIVISOR_125;
CursorDPos = LF_DIVISOR_134;
ShowGraphWindow();
RepaintGraphWindow();
} else {
@ -1726,16 +1795,26 @@ int CmdTuneSamples(const char *Cmd) {
}
static int CmdLoad(const char *Cmd) {
char filename[FILE_PATH_SIZE] = {0x00};
int len = 0;
len = strlen(Cmd);
if (len == 0) return PM3_EFILE;
CLIParserContext *ctx;
CLIParserInit(&ctx, "data load",
"This command loads the contents of a pm3 file into graph window\n",
"data load -f myfilename"
);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
void *argtable[] = {
arg_param_begin,
arg_strx0("f", "file", "<filename>", "file to load"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
char *path;
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
char *path = NULL;
if (searchFile(&path, TRACES_SUBDIR, filename, ".pm3", true) != PM3_SUCCESS) {
if (searchFile(&path, TRACES_SUBDIR, filename, "", false) != PM3_SUCCESS) {
return PM3_EFILE;
@ -1759,7 +1838,6 @@ static int CmdLoad(const char *Cmd) {
if (GraphTraceLen >= MAX_GRAPH_TRACE_LEN)
break;
}
fclose(f);
PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " samples", GraphTraceLen);
@ -1789,6 +1867,7 @@ int CmdLtrim(const char *Cmd) {
GraphBuffer[i - ds] = GraphBuffer[i];
GraphTraceLen -= ds;
g_DemodStartIdx -= ds;
RepaintGraphWindow();
return PM3_SUCCESS;
}
@ -1858,39 +1937,29 @@ int CmdPlot(const char *Cmd) {
int CmdSave(const char *Cmd) {
int len = 0;
char filename[FILE_PATH_SIZE] = {0x00};
uint8_t cmdp = 0;
bool errors = false, as_wave = false, has_name = false;
CLIParserContext *ctx;
CLIParserInit(&ctx, "data save",
"Save trace from graph window , i.e. the GraphBuffer\n"
"This is a text file with number -127 to 127. With the option `w` you can save it as wave file\n"
"Filename should be without file extension",
"data save -f myfilename -> save graph buffer to file\n"
"data save --wave -f myfilename -> save graph buffer to wave file"
);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
char ctmp = tolower(param_getchar(Cmd, cmdp));
switch (ctmp) {
case 'h':
return usage_data_save();
case 'f':
len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
if (len < 1) {
errors = true;
break;
}
has_name = true;
cmdp += 2;
break;
case 'w':
as_wave = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
void *argtable[] = {
arg_param_begin,
arg_lit0("w", "wave", "save as wave format (.wav)"),
arg_strx0("f", "file", "<fn w/o ext>", "save file name"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
if (!has_name) errors = true;
bool as_wave = arg_get_lit(ctx, 1);
if (errors || cmdp == 0) return usage_data_save();
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIGetStrWithReturn(ctx, 2, (uint8_t *)filename, &fnlen);
CLIParserFree(ctx);
if (as_wave)
return saveFileWAVE(filename, GraphBuffer, GraphTraceLen);
@ -1898,27 +1967,27 @@ int CmdSave(const char *Cmd) {
return saveFilePM3(filename, GraphBuffer, GraphTraceLen);
}
static int CmdScale(const char *Cmd) {
static int CmdTimeScale(const char *Cmd) {
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"
CLIParserInit(&ctx, "data timescale",
"Set cursor display timescale.\n"
"Setting the timescale makes the differential `dt` reading between the yellow and purple markers meaningful.\n"
"once the timescale is set, the differential reading between brackets can become a time duration.",
"data timescale --sr 125 -u ms -> for LF sampled at 125 kHz. Reading will be in milliseconds\n"
"data timescale --sr 1.695 -u us -> for HF sampled at 16 * fc/128. Reading will be in microseconds\n"
"data timescale --sr 16 -u ETU -> for HF with 16 samples per ETU (fc/128). Reading will be in ETUs"
);
void *argtable[] = {
arg_param_begin,
arg_dbl1(NULL, "sr", "<float>", "sets scale according to sampling rate"),
arg_dbl1(NULL, "sr", "<float>", "sets timescale factor 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");
PrintAndLogEx(FAILED, "bad, can't have negative or zero timescale factor");
CursorScaleFactor = 1;
}
int len = 0;
@ -2298,45 +2367,206 @@ static int CmdDataNDEF(const char *Cmd) {
return res;
}
typedef struct {
t55xx_modulation modulation;
int bitrate;
int carrier;
uint8_t fc1;
uint8_t fc2;
} lf_modulation_t;
static int print_modulation(lf_modulation_t b) {
PrintAndLogEx(INFO, " Modulation.... " _GREEN_("%s"), GetSelectedModulationStr(b.modulation));
PrintAndLogEx(INFO, " Bit clock..... " _GREEN_("RF/%d"), b.bitrate);
switch (b.modulation) {
case DEMOD_PSK1:
case DEMOD_PSK2:
case DEMOD_PSK3:
PrintAndLogEx(SUCCESS, " Carrier rate.. %d", b.carrier);
break;
case DEMOD_FSK:
case DEMOD_FSK1:
case DEMOD_FSK1a:
case DEMOD_FSK2:
case DEMOD_FSK2a:
PrintAndLogEx(SUCCESS, " Field Clocks.. FC/%u, FC/%u", b.fc1, b.fc2);
break;
case DEMOD_NRZ:
case DEMOD_ASK:
case DEMOD_BI:
case DEMOD_BIa:
default:
break;
}
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int try_detect_modulation(void) {
lf_modulation_t tests[6];
int clk = 0, firstClockEdge = 0;
uint8_t hits = 0, ans = 0;
uint8_t fc1 = 0, fc2 = 0;
bool st = false;
ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge);
if (ans && ((fc1 == 10 && fc2 == 8) || (fc1 == 8 && fc2 == 5))) {
if ((FSKrawDemod(0, 0, 0, 0, false) == PM3_SUCCESS)) {
tests[hits].modulation = DEMOD_FSK;
if (fc1 == 8 && fc2 == 5) {
tests[hits].modulation = DEMOD_FSK1a;
} else if (fc1 == 10 && fc2 == 8) {
tests[hits].modulation = DEMOD_FSK2;
}
tests[hits].bitrate = clk;
tests[hits].fc1 = fc1;
tests[hits].fc2 = fc2;
++hits;
}
} else {
clk = GetAskClock("", false);
if (clk > 0) {
// 0 = auto clock
// 0 = no invert
// 1 = maxError 1
// 0 = max len
// false = no amplify
// false = no verbose
// false = no emSearch
// 1 = Ask/Man
// st = true
if ((ASKDemod_ext(0, 0, 1, 0, false, false, false, 1, &st) == PM3_SUCCESS)) {
tests[hits].modulation = DEMOD_ASK;
tests[hits].bitrate = clk;
++hits;
}
// "0 0 1 " == clock auto, invert true, maxError 1.
// false = no verbose
// false = no emSearch
// 1 = Ask/Man
// st = true
// ASK / biphase
if ((ASKbiphaseDemod(0, 0, 0, 2, false) == PM3_SUCCESS)) {
tests[hits].modulation = DEMOD_BI;
tests[hits].bitrate = clk;
++hits;
}
// ASK / Diphase
if ((ASKbiphaseDemod(0, 0, 1, 2, false) == PM3_SUCCESS)) {
tests[hits].modulation = DEMOD_BIa;
tests[hits].bitrate = clk;
++hits;
}
}
clk = GetNrzClock("", false);
if ((NRZrawDemod(0, 0, 1, false) == PM3_SUCCESS)) {
tests[hits].modulation = DEMOD_NRZ;
tests[hits].bitrate = clk;
++hits;
}
clk = GetPskClock("", false);
if (clk > 0) {
// allow undo
save_restoreGB(GRAPH_SAVE);
// skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)
CmdLtrim("160");
if ((PSKDemod(0, 0, 6, false) == PM3_SUCCESS)) {
tests[hits].modulation = DEMOD_PSK1;
tests[hits].bitrate = clk;
++hits;
// get psk carrier
tests[hits].carrier = GetPskCarrier(false);
}
//undo trim samples
save_restoreGB(GRAPH_RESTORE);
}
}
if (hits) {
PrintAndLogEx(SUCCESS, "Found [%d] possible matches for modulation.", hits);
for (int i = 0; i < hits; ++i) {
PrintAndLogEx(INFO, "--[%d]---------------", i + 1);
print_modulation(tests[i]);
}
return PM3_SUCCESS;
} else {
PrintAndLogEx(INFO, "Signal doesn't match");
return PM3_ESOFT;
}
}
static int CmdDataModulationSearch(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "data modulation",
"search LF signal after clock and modulation\n",
"data modulation"
);
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
return try_detect_modulation();
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"askedgedetect", CmdAskEdgeDetect, AlwaysAvailable, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"},
{"autocorr", CmdAutoCorr, AlwaysAvailable, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"},
{"biphaserawdecode", CmdBiphaseDecodeRaw, AlwaysAvailable, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"},
{"bin2hex", Cmdbin2hex, AlwaysAvailable, "<digits> -- Converts binary to hexadecimal"},
{"bitsamples", CmdBitsamples, IfPm3Present, "Get raw samples as bitstring"},
{"buffclear", CmdBuffClear, AlwaysAvailable, "Clears bigbuff on deviceside and graph window"},
{"convertbitstream", CmdConvertBitStream, AlwaysAvailable, "Convert GraphBuffer's 0/1 values to 127 / -127"},
{"dec", CmdDec, AlwaysAvailable, "Decimate samples"},
{"detectclock", CmdDetectClockRate, AlwaysAvailable, "[<a|f|n|p>] Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer"},
{"-----------", CmdHelp, AlwaysAvailable, "------------------------- " _CYAN_("Modulation") "-------------------------"},
{"biphaserawdecode", CmdBiphaseDecodeRaw, AlwaysAvailable, "Biphase decode bin stream in DemodBuffer"},
{"detectclock", CmdDetectClockRate, AlwaysAvailable, "Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer"},
{"fsktonrz", CmdFSKToNRZ, AlwaysAvailable, "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)"},
{"getbitstream", CmdGetBitStream, AlwaysAvailable, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"},
{"grid", CmdGrid, AlwaysAvailable, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
{"hexsamples", CmdHexsamples, IfPm3Present, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
{"hex2bin", Cmdhex2bin, AlwaysAvailable, "<hexadecimal> -- Converts hexadecimal to binary"},
{"manrawdecode", Cmdmandecoderaw, AlwaysAvailable, "Manchester decode binary stream in DemodBuffer"},
{"modulation", CmdDataModulationSearch, AlwaysAvailable, "Identify LF signal for clock and modulation"},
{"rawdemod", CmdRawDemod, AlwaysAvailable, "Demodulate the data in the GraphBuffer and output binary"},
{"-----------", CmdHelp, AlwaysAvailable, "------------------------- " _CYAN_("Graph") "-------------------------"},
{"askedgedetect", CmdAskEdgeDetect, AlwaysAvailable, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"},
{"autocorr", CmdAutoCorr, AlwaysAvailable, "Autocorrelation over window"},
{"dirthreshold", CmdDirectionalThreshold, AlwaysAvailable, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
{"decimate", CmdDecimate, AlwaysAvailable, "Decimate samples"},
{"undecimate", CmdUndecimate, AlwaysAvailable, "Un-decimate samples"},
{"hide", CmdHide, AlwaysAvailable, "Hide graph window"},
{"hpf", CmdHpf, AlwaysAvailable, "Remove DC offset from trace"},
{"load", CmdLoad, AlwaysAvailable, "<filename> -- Load trace (to graph window"},
{"iir", CmdDataIIR, AlwaysAvailable, "apply IIR buttersworth filter on plotdata"},
{"grid", CmdGrid, AlwaysAvailable, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
{"ltrim", CmdLtrim, AlwaysAvailable, "<samples> -- Trim samples from left of trace"},
{"rtrim", CmdRtrim, AlwaysAvailable, "<location to end trace> -- Trim samples from right of trace"},
{"mtrim", CmdMtrim, AlwaysAvailable, "<start> <stop> -- Trim out samples from the specified start to the specified stop"},
{"manrawdecode", Cmdmandecoderaw, AlwaysAvailable, "[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer"},
{"norm", CmdNorm, AlwaysAvailable, "Normalize max/min to +/-128"},
{"plot", CmdPlot, AlwaysAvailable, "Show graph window (hit 'h' in window for keystroke help)"},
{"printdemodbuffer", CmdPrintDemodBuff, AlwaysAvailable, "[x] [o] <offset> [l] <length> -- print the data in the DemodBuffer - 'x' for hex output"},
{"rawdemod", CmdRawDemod, AlwaysAvailable, "[modulation] ... <options> -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"},
{"samples", CmdSamples, IfPm3Present, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"},
{"save", CmdSave, AlwaysAvailable, "Save trace (from graph window)"},
{"rtrim", CmdRtrim, AlwaysAvailable, "<location to end trace> -- Trim samples from right of trace"},
{"setgraphmarkers", CmdSetGraphMarkers, AlwaysAvailable, "[orange_marker] [blue_marker] (in graph window)"},
{"scale", CmdScale, AlwaysAvailable, "<int> -- Set cursor display scale in carrier frequency expressed in kHz"},
{"setdebugmode", CmdSetDebugMode, AlwaysAvailable, "<0|1|2> -- Set Debugging Level on client side"},
{"shiftgraphzero", CmdGraphShiftZero, AlwaysAvailable, "<shift> -- Shift 0 for Graphed wave + or - shift value"},
{"dirthreshold", CmdDirectionalThreshold, AlwaysAvailable, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
{"tune", CmdTuneSamples, IfPm3Present, "Get hw tune samples for graph window"},
{"undec", CmdUndec, AlwaysAvailable, "Un-decimate samples by 2"},
{"timescale", CmdTimeScale, AlwaysAvailable, "Set a timescale to get a differential reading between the yellow and purple markers as time duration\n"},
{"zerocrossings", CmdZerocrossings, AlwaysAvailable, "Count time between zero-crossings"},
{"iir", CmdDataIIR, AlwaysAvailable, "apply IIR buttersworth filter on plotdata"},
{"convertbitstream", CmdConvertBitStream, AlwaysAvailable, "Convert GraphBuffer's 0/1 values to 127 / -127"},
{"getbitstream", CmdGetBitStream, AlwaysAvailable, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"},
{"-----------", CmdHelp, AlwaysAvailable, "------------------------- " _CYAN_("General") "-------------------------"},
{"bin2hex", Cmdbin2hex, AlwaysAvailable, "Converts binary to hexadecimal"},
{"bitsamples", CmdBitsamples, IfPm3Present, "Get raw samples as bitstring"},
{"clear", CmdBuffClear, AlwaysAvailable, "Clears bigbuf on deviceside and graph window"},
{"hexsamples", CmdHexsamples, IfPm3Present, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
{"hex2bin", Cmdhex2bin, AlwaysAvailable, "Converts hexadecimal to binary"},
{"load", CmdLoad, AlwaysAvailable, "Load contents of file into graph window"},
{"ndef", CmdDataNDEF, AlwaysAvailable, "Decode NDEF records"},
{"print", CmdPrintDemodBuff, AlwaysAvailable, "print the data in the DemodBuffer"},
{"samples", CmdSamples, IfPm3Present, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"},
{"save", CmdSave, AlwaysAvailable, "Save signal trace data (from graph window)"},
{"setdebugmode", CmdSetDebugMode, AlwaysAvailable, "<0|1|2> -- Set Debugging Level on client side"},
{"tune", CmdTuneSamples, IfPm3Present, "Measure tuning of device antenna. Results shown in graph window"},
{NULL, NULL, NULL, NULL}
};

View file

@ -60,7 +60,7 @@ int CmdPlot(const char *Cmd);
int CmdSave(const char *Cmd); // used by cmd auto
int CmdTuneSamples(const char *Cmd); // used by cmd lf hw
int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose); // used by cmd lf em4x, lf fdx, lf guard, lf jablotron, lf nedap, lf t55xx
int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose); // used by cmd lf em4x, lf fdxb, lf guard, lf jablotron, lf nedap, lf t55xx
int ASKDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool verbose, bool emSearch, uint8_t askType); // used by cmd lf em4x, lf t55xx, lf viking
int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool verbose, bool emSearch, uint8_t askType, bool *stCheck); // used by cmd lf, lf em4x, lf noralsy, le presco, lf securekey, lf t55xx, lf visa2k
int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bool verbose); // used by cmd lf, lf em4x, lf t55xx
@ -86,7 +86,7 @@ extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
extern size_t DemodBufferLen;
extern int g_DemodClock;
extern size_t g_DemodStartIdx;
extern int32_t g_DemodStartIdx;
#ifdef __cplusplus
}

View file

@ -459,7 +459,7 @@ static int CmdFlashMemInfo(const char *Cmd) {
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, "Len.................. %"PRIu64, rsa.len);
PrintAndLogEx(INFO, "Exponent............. %s", str_exp);
PrintAndLogEx(INFO, "Public key modulus N");
PrintAndLogEx(INFO, " %.64s", str_pk);

View file

@ -269,9 +269,13 @@ static int usage_hf_14a_reader(void) {
}
static int CmdHF14AList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("14a");
return 0;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t 14a");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
int hf14a_getconfig(hf14a_config *config) {
@ -1267,14 +1271,14 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
*buf = 0;
if (++datalen >= sizeof(data)) {
if (crc)
PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data");
PrintAndLogEx(FAILED, "Buffer is full, we can't add CRC to your data");
break;
}
}
continue;
}
PrintAndLogEx(NORMAL, "Invalid char on input");
return 0;
PrintAndLogEx(FAILED, "Invalid char on input");
return PM3_ESOFT;
}
if (crc && datalen > 0 && datalen < sizeof(data) - 2) {
@ -1301,7 +1305,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
flags |= ISO14A_SET_TIMEOUT;
if (timeout > MAX_TIMEOUT) {
timeout = MAX_TIMEOUT;
PrintAndLogEx(NORMAL, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
PrintAndLogEx(INFO, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
}
argtimeout = 13560000 / 1000 / (8 * 16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
}
@ -1345,18 +1349,32 @@ static int waitCmd(uint8_t iSelect, uint32_t timeout) {
if (iSelect) {
len = (resp.oldarg[1] & 0xFFFF);
if (len) {
PrintAndLogEx(NORMAL, "Card selected. UID[%i]:", len);
PrintAndLogEx(SUCCESS, "Card selected. UID[%u]:", len);
} else {
PrintAndLogEx(WARNING, "Can't select card.");
}
} else {
PrintAndLogEx(NORMAL, "received %i bytes", len);
PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len);
}
if (!len)
return 1;
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.data.asBytes, len));
uint8_t *data = resp.data.asBytes;
if (len >= 3) {
bool crc = check_crc(CRC_14443_A, data, len);
PrintAndLogEx(SUCCESS, "%s[%02X %02X] %s",
sprint_hex(data, len - 2),
data[len - 2],
data[len - 1],
(crc) ? _GREEN_("ok") : _RED_("fail")
);
} else {
PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
}
} else {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 3;
@ -1954,6 +1972,9 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
}
} else {
PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported");
if ((card.sak & 0x20) == 0x20) {
PrintAndLogEx(INFO, "SAK incorrectly claims that card supports RATS");
}
}
int isMagic = 0;

View file

@ -79,7 +79,8 @@ static bool wait_cmd_14b(bool verbose, bool is_select) {
if (status == 0) {
if (verbose) {
PrintAndLogEx(SUCCESS, "len %u | %s", len, sprint_hex(data, len));
PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len);
PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
}
return true;
} else {
@ -93,8 +94,8 @@ static bool wait_cmd_14b(bool verbose, bool is_select) {
if (len >= 3) {
bool crc = check_crc(CRC_14443_B, data, len);
PrintAndLogEx(SUCCESS, "len %u | %s[%02X %02X] %s",
len,
PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len);
PrintAndLogEx(SUCCESS, "%s[%02X %02X] %s",
sprint_hex(data, len - 2),
data[len - 2],
data[len - 1],
@ -104,20 +105,24 @@ static bool wait_cmd_14b(bool verbose, bool is_select) {
if (verbose)
PrintAndLogEx(INFO, "no response from tag");
} else {
PrintAndLogEx(SUCCESS, "len %u | %s", len, sprint_hex(data, len));
PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
}
}
return true;
} else {
PrintAndLogEx(WARNING, "command execution timeout");
PrintAndLogEx(WARNING, "timeout while waiting for reply");
return false;
}
}
static int CmdHF14BList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("14b");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t 14b");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static int CmdHF14BSim(const char *Cmd) {
@ -139,11 +144,12 @@ static int CmdHF14BSim(const char *Cmd) {
uint8_t pupi[4];
int n = 0;
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), pupi, sizeof(pupi), &n);
CLIParserFree(ctx);
if (res) {
PrintAndLogEx(FAILED, "failed to read pupi");
return PM3_EINVARG;
}
CLIParserFree(ctx);
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi));
return PM3_SUCCESS;
@ -188,11 +194,11 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
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("s", "std", "activate field, use ISO14B select"),
arg_lit0(NULL, "sr", "activate field, use SRx ST select"),
arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"),
arg_lit0("c", "crc", "calculate and append CRC"),
arg_lit0("r", "noresponse", "do not read response"),
arg_lit0("r", "noresponse", "do not read response from card"),
arg_int0("t", "timeout", "<dec>", "timeout in ms"),
arg_lit0("v", "verbose", "verbose"),
arg_strx0("d", "data", "<hex>", "data, bytes to send"),
@ -217,7 +223,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
if (select_std) {
flags |= (ISO14B_SELECT_STD | ISO14B_CLEARTRACE);
if (verbose)
PrintAndLogEx(INFO, "using standard select");
PrintAndLogEx(INFO, "using ISO14443-B select");
} else if (select_sr) {
flags |= (ISO14B_SELECT_SR | ISO14B_CLEARTRACE);
if (verbose)
@ -267,6 +273,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
}
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);
@ -650,7 +657,7 @@ static bool HF14B_Std_Info(bool verbose) {
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0);
if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply");
switch_off_field_14b();
return is_success;
}
@ -690,7 +697,7 @@ static bool HF14B_ST_Info(bool verbose) {
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0);
if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply");
return false;
}
@ -734,7 +741,7 @@ static bool HF14B_st_reader(bool verbose) {
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0);
if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply");
return is_success;
}
@ -774,7 +781,7 @@ static bool HF14B_std_reader(bool verbose) {
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply");
return false;
}
@ -817,7 +824,7 @@ static bool HF14B_ask_ct_reader(bool verbose) {
PacketResponseNG resp;
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_CTS | ISO14B_DISCONNECT, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply");
return false;
}
@ -859,7 +866,7 @@ static bool HF14B_other_reader(bool verbose) {
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, datalen, 0, data, datalen);
if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply");
switch_off_field_14b();
return false;
}
@ -883,7 +890,7 @@ static bool HF14B_other_reader(bool verbose) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, 1, 0, data, 1);
if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply");
switch_off_field_14b();
return false;
}
@ -907,7 +914,7 @@ static bool HF14B_other_reader(bool verbose) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, 1, 0, data, 1);
if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply");
switch_off_field_14b();
return false;
}

View file

@ -60,9 +60,9 @@ typedef struct {
uint64_t uid;
int mask; // how many MSB bits used
const char *desc;
} productName;
} productName_t;
const productName uidmapping[] = {
const productName_t uidmapping[] = {
// UID, #significant Bits, "Vendor(+Product)"
{ 0xE001000000000000LL, 16, "Motorola UK" },
@ -1342,9 +1342,13 @@ static int CmdHF15Dump(const char *Cmd) {
}
static int CmdHF15List(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("15");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t 15");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static int CmdHF15Raw(const char *Cmd) {

View file

@ -115,9 +115,13 @@ static int switch_off_field_cryptorf(void) {
}
static int CmdHFCryptoRFList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("cryptorf");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t cryptorf");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static int CmdHFCryptoRFSim(const char *Cmd) {

View file

@ -407,9 +407,13 @@ static bool add_last_IDm(uint8_t position, uint8_t *data) {
}
static int CmdHFFelicaList(const char *Cmd) {
(void)Cmd;
CmdTraceList("felica");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t felica");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static int CmdHFFelicaReader(const char *Cmd) {

View file

@ -36,10 +36,21 @@
#include "emv/dump.h"
#include "ui.h"
#include "cmdhf14a.h"
#include "cmdtrace.h"
static int CmdHelp(const char *Cmd);
static int CmdHFFidoInfo(const char *cmd) {
static int cmd_hf_fido_list(const char *Cmd) {
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t 14a");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static int cmd_hf_fido_info(const char *cmd) {
if (cmd && strlen(cmd) > 0)
PrintAndLogEx(WARNING, "WARNING: command doesn't have any parameters.\n");
@ -150,7 +161,7 @@ static json_t *OpenJson(CLIParserContext *ctx, int paramnum, char *fname, void *
return root;
}
static int CmdHFFidoRegister(const char *cmd) {
static int cmd_hf_fido_register(const char *cmd) {
uint8_t data[64] = {0};
int chlen = 0;
uint8_t cdata[250] = {0};
@ -386,7 +397,7 @@ static int CmdHFFidoRegister(const char *cmd) {
return PM3_SUCCESS;
}
static int CmdHFFidoAuthenticate(const char *cmd) {
static int cmd_hf_fido_authenticate(const char *cmd) {
uint8_t data[512] = {0};
uint8_t hdata[250] = {0};
bool public_key_loaded = false;
@ -652,7 +663,7 @@ static int GetExistsFileNameJson(const char *prefixDir, const char *reqestedFile
return PM3_SUCCESS;
}
static int CmdHFFido2MakeCredential(const char *cmd) {
static int cmd_hf_fido_2make_credential(const char *cmd) {
json_error_t error;
char fname[FILE_PATH_SIZE] = {0};
@ -777,7 +788,7 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
return PM3_SUCCESS;
}
static int CmdHFFido2GetAssertion(const char *cmd) {
static int cmd_hf_fido_2get_assertion(const char *cmd) {
json_error_t error;
char fname[FILE_PATH_SIZE] = {0};
@ -904,11 +915,12 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help."},
{"info", CmdHFFidoInfo, IfPm3Iso14443a, "Info about FIDO tag."},
{"reg", CmdHFFidoRegister, IfPm3Iso14443a, "FIDO U2F Registration Message."},
{"auth", CmdHFFidoAuthenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."},
{"make", CmdHFFido2MakeCredential, IfPm3Iso14443a, "FIDO2 MakeCredential command."},
{"assert", CmdHFFido2GetAssertion, IfPm3Iso14443a, "FIDO2 GetAssertion command."},
{"info", cmd_hf_fido_list, IfPm3Iso14443a, "List ISO 14443A history"},
{"info", cmd_hf_fido_info, IfPm3Iso14443a, "Info about FIDO tag."},
{"reg", cmd_hf_fido_register, IfPm3Iso14443a, "FIDO U2F Registration Message."},
{"auth", cmd_hf_fido_authenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."},
{"make", cmd_hf_fido_2make_credential, IfPm3Iso14443a, "FIDO2 MakeCredential command."},
{"assert", cmd_hf_fido_2get_assertion, IfPm3Iso14443a, "FIDO2 GetAssertion command."},
{NULL, NULL, 0, NULL}
};

View file

@ -18,6 +18,7 @@
#include "cmdparser.h" // command_t
#include "commonutil.h" // ARRAYLEN
#include "cmdtrace.h"
#include "cliparser.h"
#include "util_posix.h"
#include "comms.h"
#include "des.h"
@ -224,21 +225,6 @@ static int usage_hf_iclass_readblock(void) {
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_iclass_view(void) {
PrintAndLogEx(NORMAL, "Print a iCLASS tag dump file\n");
PrintAndLogEx(NORMAL, "Usage: hf iClass view [f <filename>] [s <startblock>] [e <endblock>] [v]\n");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h Show this help");
PrintAndLogEx(NORMAL, " f <filename> filename of dump");
PrintAndLogEx(NORMAL, " s <startblock> print from this block (default block6)");
PrintAndLogEx(NORMAL, " e <endblock> end printing at this block (default 0, ALL)");
PrintAndLogEx(NORMAL, " v verbose output");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass view f hf-iclass-AA162D30F8FF12F1-dump.bin"));
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass view s 1 f hf-iclass-AA162D30F8FF12F1-dump.bin"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_iclass_calc_newkey(void) {
PrintAndLogEx(NORMAL, "Calculate new key for updating\n");
PrintAndLogEx(NORMAL, "Usage: hf iclass calc_newkey o <old key> n <new key> s [csn] e\n");
@ -359,20 +345,7 @@ static int usage_hf_iclass_lookup(void) {
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_iclass_permutekey(void) {
PrintAndLogEx(NORMAL, "Permute function from 'heart of darkness' paper.\n");
PrintAndLogEx(NORMAL, "Usage: hf iclass permute [h] <r|f> <bytes>\n");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h Show this help");
PrintAndLogEx(NORMAL, " r reverse permuted key");
PrintAndLogEx(NORMAL, " f permute key");
PrintAndLogEx(NORMAL, " <bytes> input bytes");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass permute r 0123456789abcdef"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int cmp_uint32(const void *a, const void *b) {
@ -631,9 +604,13 @@ static void print_picopass_header(const picopass_hdr *hdr) {
}
static int CmdHFiClassList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("iclass");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t iclass");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static int CmdHFiClassSniff(const char *Cmd) {
@ -2680,43 +2657,31 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
}
static int CmdHFiClassView(const char *Cmd) {
int startblock = 0;
int endblock = 0;
char filename[FILE_PATH_SIZE];
bool errors = false, verbose = false;
uint8_t cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_hf_iclass_view();
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 's':
startblock = param_get8ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'e':
endblock = param_get8ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'v':
verbose = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass view",
"Print a iCLASS tag dump file",
"hf iclass view -f hf-iclass-AA162D30F8FF12F1-dump.bin\n"
"hf iclass view --startblock 1 --file hf-iclass-AA162D30F8FF12F1-dump.bin\n");
if (errors || (strlen(Cmd) == 0)) return usage_hf_iclass_view();
void *argtable[] = {
arg_param_begin,
arg_str1("f", "file", "<filename>", "filename of dump"),
arg_int0("s", "startblock", "<dec>", "print from this block (default block6)"),
arg_int0("e", "endblock", "<dec>", "end printing at this block (default 0, ALL)"),
arg_lit0("v", "verbose", "verbose output"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int fnlen = 0;
char filename[FILE_PATH_SIZE];
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
int startblock = arg_get_int_def(ctx, 2, 0);
int endblock = arg_get_int_def(ctx, 3, 0);
bool verbose = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
uint8_t *dump = NULL;
size_t bytes_read = 0;
@ -3522,17 +3487,26 @@ static int CmdHFiClassPermuteKey(const char *Cmd) {
uint8_t data[16] = {0};
bool isReverse = false;
int len = 0;
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h')
return usage_hf_iclass_permutekey();
isReverse = (cmdp == 'r');
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass permute",
"Permute function from 'heart of darkness' paper.",
"hf iclass permute --reverse --key 0123456789abcdef\n"
"hf iclass permute --key ff55330f0055330f\n");
param_gethex_ex(Cmd, 1, data, &len);
if (len % 2)
return usage_hf_iclass_permutekey();
void *argtable[] = {
arg_param_begin,
arg_lit0("r", "reverse", "reverse permuted key"),
arg_str1(NULL, "key", "<bytes>", "input key"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
len >>= 1;
isReverse = arg_get_lit(ctx, 1);
CLIGetHexWithReturn(ctx, 2, data, &len);
CLIParserFree(ctx);
memcpy(key, data, 8);
@ -3580,7 +3554,7 @@ static command_t CommandTable[] = {
{"encrypt", CmdHFiClassEncryptBlk, AlwaysAvailable, "[options..] Encrypt given block data"},
{"decrypt", CmdHFiClassDecrypt, AlwaysAvailable, "[options..] Decrypt given block data or tag dump file" },
{"managekeys", CmdHFiClassManageKeys, AlwaysAvailable, "[options..] Manage keys to use with iclass commands"},
{"permutekey", CmdHFiClassPermuteKey, IfPm3Iclass, " Permute function from 'heart of darkness' paper"},
{"permute", CmdHFiClassPermuteKey, IfPm3Iclass, " Permute function from 'heart of darkness' paper"},
{"view", CmdHFiClassView, AlwaysAvailable, "[options..] Display content from tag dump file"},
{NULL, NULL, NULL, NULL}

View file

@ -1401,9 +1401,13 @@ static int CmdLegicWipe(const char *Cmd) {
}
static int CmdLegicList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("legic");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t legic");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static command_t CommandTable[] = {

View file

@ -207,9 +207,13 @@ int infoLTO(bool verbose) {
}
static int CmdHfLTOList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("lto");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t lto");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static int lto_rdbl(uint8_t blk, uint8_t *block_responce, uint8_t *block_cnt_responce, bool verbose) {

View file

@ -1002,6 +1002,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
return PM3_ESOFT;
strcpy(keyFilename, fptr);
free(fptr);
}
if ((f = fopen(keyFilename, "rb")) == NULL) {
@ -1163,6 +1164,7 @@ static int CmdHF14AMfDump(const char *Cmd) {
return PM3_ESOFT;
strcpy(dataFilename, fptr);
free(fptr);
}
uint16_t bytes = 16 * (FirstBlockOfSector(numSectors - 1) + NumBlocksPerSector(numSectors - 1));
@ -1226,6 +1228,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
return 1;
strcpy(keyFilename, fptr);
free(fptr);
}
if ((fkeys = fopen(keyFilename, "rb")) == NULL) {
@ -1260,6 +1263,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
return 1;
strcpy(dataFilename, fptr);
free(fptr);
}
if ((fdump = fopen(dataFilename, "rb")) == NULL) {
@ -1570,8 +1574,10 @@ jumptoend:
if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Failed to save keys to file");
free(e_sector);
free(fptr);
return PM3_ESOFT;
}
free(fptr);
}
free(e_sector);
}
@ -1775,8 +1781,10 @@ jumptoend:
if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Failed to save keys to file");
free(e_sector);
free(fptr);
return PM3_ESOFT;
}
free(fptr);
}
free(e_sector);
@ -2013,7 +2021,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
uint8_t block[16] = {0x00};
uint8_t *dump;
int bytes;
char *fnameptr = filename;
// Settings
bool slow = false;
bool legacy_mfchk = false;
@ -2136,7 +2143,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
// read uid to generate a filename for the key file
char *fptr = GenerateFilename("hf-mf-", "-key.bin");
// check if tag doesn't have static nonce
has_staticnonce = detect_classic_static_nonce();
@ -2146,6 +2152,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
if (prng_type < 0) {
PrintAndLogEx(FAILED, "\nNo tag detected or other tag communication error");
free(e_sector);
free(fptr);
return prng_type;
}
}
@ -2259,6 +2266,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6);
if (keyBlock == NULL) {
free(e_sector);
free(fptr);
return PM3_EMALLOC;
}
@ -2403,6 +2411,7 @@ noValidKeyFound:
PrintAndLogEx(FAILED, "No usable key was found!");
free(keyBlock);
free(e_sector);
free(fptr);
return PM3_ESOFT;
}
}
@ -2516,11 +2525,13 @@ tryNested:
case PM3_ETIMEOUT: {
PrintAndLogEx(ERR, "\nError: No response from Proxmark3.");
free(e_sector);
free(fptr);
return PM3_ESOFT;
}
case PM3_EOPABORTED: {
PrintAndLogEx(WARNING, "\nButton pressed. Aborted.");
free(e_sector);
free(fptr);
return PM3_EOPABORTED;
}
case PM3_EFAILED: {
@ -2551,6 +2562,7 @@ tryNested:
default: {
PrintAndLogEx(ERR, "unknown Error.\n");
free(e_sector);
free(fptr);
return PM3_ESOFT;
}
}
@ -2582,6 +2594,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
}
}
free(e_sector);
free(fptr);
return PM3_ESOFT;
}
@ -2606,11 +2619,13 @@ tryStaticnested:
case PM3_ETIMEOUT: {
PrintAndLogEx(ERR, "\nError: No response from Proxmark3.");
free(e_sector);
free(fptr);
return PM3_ESOFT;
}
case PM3_EOPABORTED: {
PrintAndLogEx(WARNING, "\nButton pressed. Aborted.");
free(e_sector);
free(fptr);
return PM3_EOPABORTED;
}
case PM3_SUCCESS: {
@ -2676,6 +2691,7 @@ all_found:
if (!dump) {
PrintAndLogEx(ERR, "Fail, cannot allocate memory");
free(e_sector);
free(fptr);
return PM3_EMALLOC;
}
memset(dump, 0, bytes);
@ -2685,16 +2701,19 @@ all_found:
PrintAndLogEx(ERR, "Fail, transfer from device time-out");
free(e_sector);
free(dump);
free(fptr);
return PM3_ETIMEOUT;
}
fnameptr = GenerateFilename("hf-mf-", "-dump");
char *fnameptr = GenerateFilename("hf-mf-", "-dump");
if (fnameptr == NULL) {
free(dump);
free(e_sector);
free(fptr);
return PM3_ESOFT;
}
strcpy(filename, fnameptr);
free(fnameptr);
saveFile(filename, ".bin", dump, bytes);
saveFileEML(filename, dump, bytes, MFBLOCK_SIZE);
@ -2706,6 +2725,7 @@ all_found:
free(dump);
free(e_sector);
free(fptr);
return PM3_SUCCESS;
}
@ -2982,6 +3002,7 @@ out:
if (createMfcKeyDump(fptr, sectorsCnt, e_sector) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Failed to save keys to file");
}
free(fptr);
}
}
@ -3285,6 +3306,7 @@ out:
if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Failed to save keys to file");
}
free(fptr);
}
free(keyBlock);
@ -4040,7 +4062,6 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) {
char *fptr = filename;
fptr += snprintf(fptr, sizeof(filename), "hf-mf-");
FillFileNameByUID(fptr + strlen(fptr), uid, "-key", sizeof(uid));
createMfcKeyDump(filename, sectors_cnt, e_sector);
}
@ -4732,6 +4753,7 @@ static int CmdHF14AMfice(const char *Cmd) {
if (fptr == NULL)
return PM3_EFILE;
strcpy(filename, fptr);
free(fptr);
}
PrintAndLogEx(NORMAL, "Collecting "_YELLOW_("%u")" nonces \n", limit);
@ -5174,8 +5196,13 @@ static int CmdHFMFPersonalize(const char *cmd) {
}
static int CmdHF14AMfList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
return CmdTraceList("mf");
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t mf");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static int CmdHf14AGen3UID(const char *Cmd) {

View file

@ -4470,8 +4470,13 @@ static int CmdHF14aDesChk(const char *Cmd) {
}
static int CmdHF14ADesList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
return CmdTraceList("des");
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t des");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
/*

View file

@ -143,12 +143,10 @@ static inline void clear_bitarray24(uint32_t *bitarray) {
memset(bitarray, 0x00, sizeof(uint32_t) * (1 << 19));
}
static inline void set_bitarray24(uint32_t *bitarray) {
memset(bitarray, 0xff, sizeof(uint32_t) * (1 << 19));
}
static inline void set_bit24(uint32_t *bitarray, uint32_t index) {
bitarray[index >> 5] |= 0x80000000 >> (index & 0x0000001f);
}
@ -157,36 +155,46 @@ static inline uint32_t test_bit24(uint32_t *bitarray, uint32_t index) {
return bitarray[index >> 5] & (0x80000000 >> (index & 0x0000001f));
}
static inline uint32_t next_state(uint32_t *bitarray, uint32_t state) {
if (++state == 1 << 24) return 1 << 24;
if (++state == (1 << 24)) {
return (1 << 24);
}
uint32_t index = state >> 5;
uint_fast8_t bit = state & 0x1f;
uint_fast8_t bit = state & 0x1F;
uint32_t line = bitarray[index] << bit;
while (bit <= 0x1f) {
if (line & 0x80000000) return state;
while (bit <= 0x1F) {
if (line & 0x80000000) {
return state;
}
state++;
bit++;
line <<= 1;
}
index++;
while (bitarray[index] == 0x00000000 && state < 1 << 24) {
while (state < (1 << 24) && bitarray[index] == 0x00000000) {
index++;
state += 0x20;
}
if (state >= 1 << 24) return 1 << 24;
if (state >= (1 << 24)) {
return (1 << 24);
}
#if defined __GNUC__
return state + __builtin_clz(bitarray[index]);
#else
bit = 0x00;
line = bitarray[index];
while (bit <= 0x1f) {
if (line & 0x80000000) return state;
while (bit <= 0x1F) {
if (line & 0x80000000) {
return state;
}
state++;
bit++;
line <<= 1;
}
return 1 << 24;
return (1 << 24);
#endif
}

View file

@ -24,7 +24,7 @@
#define MAX_UL_BLOCKS 0x0F
#define MAX_ULC_BLOCKS 0x2B
#define MAX_ULC_BLOCKS 0x2F
#define MAX_ULEV1a_BLOCKS 0x13
#define MAX_ULEV1b_BLOCKS 0x28
#define MAX_NTAG_203 0x29
@ -168,17 +168,13 @@ static int usage_hf_mfu_sim(void) {
}
static int usage_hf_mfu_ucauth(void) {
PrintAndLogEx(NORMAL, "Usage: hf mfu cauth k <key number>");
PrintAndLogEx(NORMAL, " 0 (default): 3DES standard key");
PrintAndLogEx(NORMAL, " 1 : all 0x00 key");
PrintAndLogEx(NORMAL, " 2 : 0x00-0x0F key");
PrintAndLogEx(NORMAL, " 3 : nfc key");
PrintAndLogEx(NORMAL, " 4 : all 0x01 key");
PrintAndLogEx(NORMAL, " 5 : all 0xff key");
PrintAndLogEx(NORMAL, " 6 : 0x00-0xFF key");
PrintAndLogEx(NORMAL, "Tests 3DES password on Mifare Ultralight-C tag.");
PrintAndLogEx(NORMAL, "If password is not specified, a set of known defaults will be tested.");
PrintAndLogEx(NORMAL, "Usage: hf mfu cauth <password (32 hex symbols)>");
PrintAndLogEx(NORMAL, " [password] - (32 hex symbols)");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu cauth k"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu cauth k 3"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu cauth"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu cauth 000102030405060708090a0b0c0d0e0f"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
@ -244,12 +240,14 @@ static int usage_hf_mfu_otp_tearoff(void) {
PrintAndLogEx(NORMAL, " s <time> : (optional) start time to run the test - default 0 us");
PrintAndLogEx(NORMAL, " d <data> : (optional) data to full-write before trying the OTP test - default 0x00");
PrintAndLogEx(NORMAL, " t <data> : (optional) data to write while running the OTP test - default 0x00");
PrintAndLogEx(NORMAL, " m <data> : (optional) exit criteria, if block matches this value");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3");
PrintAndLogEx(NORMAL, " hf mfu otptear b 8 i 100 l 3000 s 1000");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3 i 1 l 200");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3 i 100 l 2500 s 200 d FFFFFFFF t EEEEEEEE");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3 i 100 l 2500 s 200 d FFFFFFFF t EEEEEEEE m 00000000 -> such quite when OTP is reset");
return PM3_SUCCESS;
}
@ -408,6 +406,18 @@ static int ulc_authentication(uint8_t *key, bool switch_off_field) {
return 0;
}
static int try_default_3des_keys(uint8_t **correct_key) {
PrintAndLogEx(INFO, "Trying some default 3des keys");
for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) {
uint8_t *key = default_3des_keys[i];
if (ulc_authentication(key, true)) {
*correct_key = key;
return 1;
}
}
return 0;
}
static int ulev1_requestAuthentication(uint8_t *pwd, uint8_t *pack, uint16_t packLength) {
uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]};
@ -1317,16 +1327,11 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
if (hasAuthKey) return PM3_SUCCESS;
// also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
PrintAndLogEx(INFO, "Trying some default 3des keys");
for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) {
key = default_3des_keys[i];
if (ulc_authentication(key, true)) {
if (try_default_3des_keys(&key)) {
PrintAndLogEx(SUCCESS, "Found default 3des key: ");
uint8_t keySwap[16];
memcpy(keySwap, SwapEndian64(key, 16, 8), 16);
ulc_print_3deskey(keySwap);
return PM3_SUCCESS;
}
}
return PM3_SUCCESS;
}
@ -2389,28 +2394,33 @@ static int CmdHF14AMfUSim(const char *Cmd) {
//-------------------------------------------------------------------------------
//
// Ultralight C Authentication Demo {currently uses hard-coded key}
// Ultralight C Authentication
//
static int CmdHF14AMfUCAuth(const char *Cmd) {
uint8_t keyNo = 3;
bool errors = false;
char cmdp = tolower(param_getchar(Cmd, 0));
//Change key to user defined one
if (cmdp == 'k') {
keyNo = param_get8(Cmd, 1);
if (keyNo >= ARRAYLEN(default_3des_keys))
errors = true;
if (cmdp == 'h') {
return usage_hf_mfu_ucauth();
}
if (cmdp == 'h') errors = true;
uint8_t key_buf[16];
uint8_t *key;
int succeeded;
if (errors) return usage_hf_mfu_ucauth();
// If no hex key is specified, try all known ones
if (strlen(Cmd) == 0) {
succeeded = try_default_3des_keys(&key);
// Else try user-supplied
} else {
if (param_gethex(Cmd, 0, key_buf, 32)) {
PrintAndLogEx(WARNING, "Password must include 32 HEX symbols");
return PM3_EINVARG;
}
succeeded = ulc_authentication(key_buf, true);
key = key_buf;
}
uint8_t *key = default_3des_keys[keyNo];
if (ulc_authentication(key, true))
if (succeeded)
PrintAndLogEx(SUCCESS, "Authentication successful. 3des key: %s", sprint_hex(key, 16));
else
PrintAndLogEx(WARNING, "Authentication failed");
@ -2809,7 +2819,8 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) {
static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
uint8_t blockNoUint = 8;
uint8_t cmdp = 0;
bool errors = 0;
bool errors = 0, use_match = false;
uint8_t match[4] = {0x00};
uint8_t teardata[8] = {0x00};
uint32_t interval = 500; // time in us
uint32_t timeLimit = 3000; // time in us
@ -2821,7 +2832,6 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
return usage_hf_mfu_otp_tearoff();
case 'b':
blockNoUint = param_get8(Cmd, cmdp + 1);
//iceman, which blocks can be targeted? UID blocks?
if (blockNoUint < 2) {
PrintAndLogEx(WARNING, "Wrong block number");
errors = true;
@ -2830,10 +2840,6 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
break;
case 'i':
interval = param_get32ex(Cmd, cmdp + 1, interval, 10);
if (interval == 0) {
PrintAndLogEx(WARNING, "Wrong interval number");
errors = true;
}
cmdp += 2;
break;
case 'l':
@ -2842,6 +2848,10 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
PrintAndLogEx(WARNING, "Wrong time limit number");
errors = true;
}
if (timeLimit > 43000) {
PrintAndLogEx(WARNING, "You can't set delay out of 1..43000 range!");
errors = true;
}
cmdp += 2;
break;
case 's':
@ -2866,6 +2876,14 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
}
cmdp += 2;
break;
case 'm':
if (param_gethex(Cmd, cmdp + 1, match, 8)) {
PrintAndLogEx(WARNING, "Block data must include 8 HEX symbols");
errors = true;
}
use_match = true;
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
@ -2875,52 +2893,112 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
if (errors) return usage_hf_mfu_otp_tearoff();
PrintAndLogEx(INFO, "Starting TearOff test - Selected Block no: %u", blockNoUint);
PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Tear off") " ---------------------");
PrintAndLogEx(INFO, "Starting Tear-off test");
PrintAndLogEx(INFO, "Target block no: %u", blockNoUint);
PrintAndLogEx(INFO, "Target inital block data : %s", sprint_hex_inrow(teardata, 4));
PrintAndLogEx(INFO, "Target write block data : %s", sprint_hex_inrow(teardata + 4, 4));
PrintAndLogEx(INFO, "----------------------------------------------------");
uint8_t isOK;
bool got_pre = false, got_post = false, lock_on = false;
uint8_t pre[4] = {0};
uint8_t post[4] = {0};
uint32_t actualTime = startTime;
int phase_clear = -1;
int phase_newwr = -1;
uint8_t retries = 0;
while (actualTime <= (timeLimit - interval)) {
PrintAndLogEx(INFO, "Using tear-off at: %" PRIu32 " us", actualTime);
PrintAndLogEx(INFO, "Reading block BEFORE attack");
if (kbd_enter_pressed()) {
PrintAndLogEx(INFO, "\naborted via keyboard!\n");
break;
}
PrintAndLogEx(INFO, "Using tear-off delay " _GREEN_("%" PRIu32) " us", actualTime);
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFAREU_READBL, blockNoUint, 0, 0, NULL, 0);
PacketResponseNG resp;
got_pre = false;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
isOK = resp.oldarg[0] & 0xFF;
if (isOK) {
uint8_t *d = resp.data.asBytes;
PrintAndLogEx(NORMAL, "\nBlock# | Data | Ascii");
PrintAndLogEx(NORMAL, "-----------------------------");
PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s\n", blockNoUint, blockNoUint, sprint_hex(d, 4), sprint_ascii(d, 4));
memcpy(pre, resp.data.asBytes, sizeof(pre));
got_pre = true;
}
}
PrintAndLogEx(INFO, ".....");
clearCommandBuffer();
SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF, blockNoUint, actualTime, 0, teardata, 8);
if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 4000)) {
if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 2000)) {
PrintAndLogEx(WARNING, "Failed");
return PM3_ESOFT;
}
PrintAndLogEx(INFO, "Reading block AFTER attack");
got_post = false;
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFAREU_READBL, blockNoUint, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
isOK = resp.oldarg[0] & 0xFF;
if (isOK) {
uint8_t *d = resp.data.asBytes;
PrintAndLogEx(NORMAL, "\nBlock# | Data | Ascii");
PrintAndLogEx(NORMAL, "-----------------------------");
PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s\n", blockNoUint, blockNoUint, sprint_hex(d, 4), sprint_ascii(d, 4));
memcpy(post, resp.data.asBytes, sizeof(post));
got_post = true;
}
}
if (got_pre && got_post) {
char prestr[20] = {0};
snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
char poststr[20] = {0};
snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post)));
if (memcmp(pre, post, sizeof(pre)) == 0) {
PrintAndLogEx(INFO, "Current %02d (0x%02X) %s"
, blockNoUint
, blockNoUint
, poststr
);
} else {
// skip first message, since its the reset write.
if (actualTime == startTime) {
PrintAndLogEx(INFO, "Inital write");
} else {
PrintAndLogEx(INFO, _CYAN_("Tear off occured") " : %02d (0x%02X) %s vs " _RED_("%s")
, blockNoUint
, blockNoUint
, prestr
, poststr
);
lock_on = true;
if (phase_clear == -1)
phase_clear = actualTime;
// new write phase must be atleast 100us later..
if (phase_clear > -1 && phase_newwr == -1 && actualTime > (phase_clear + 100))
phase_newwr = actualTime;
}
}
if (use_match && memcmp(pre, match, sizeof(pre)) == 0) {
PrintAndLogEx(SUCCESS, "Block matches!\n");
break;
}
} else {
if (got_pre == false)
PrintAndLogEx(FAILED, "Failed to read block BEFORE");
if (got_post == false)
PrintAndLogEx(FAILED, "Failed to read block AFTER");
}
/* TEMPORALLY DISABLED
uint8_t d0, d1, d2, d3;
d0 = *resp.data.asBytes;
@ -2933,8 +3011,29 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
PrintAndLogEx(NORMAL, "---------------------------------\n");
}
*/
if (startTime != timeLimit) {
actualTime += interval;
} else {
if (lock_on == false) {
if (++retries == 20) {
actualTime++;
timeLimit++;
startTime++;
retries = 0;
PrintAndLogEx(INFO, _CYAN_("Retried %u times, increased delay with 1us"), retries);
}
}
}
}
PrintAndLogEx(INFO, "----------------------------------------------------");
if (phase_clear > - 1) {
PrintAndLogEx(INFO, "New phase boundary around " _YELLOW_("%d") " us", phase_clear);
}
if (phase_newwr > - 1) {
PrintAndLogEx(INFO, "New phase boundary around " _YELLOW_("%d") " us", phase_newwr);
}
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}

View file

@ -724,9 +724,13 @@ static int cmd_hf_st_pwd(const char *Cmd) {
}
static int cmd_hf_st_list(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("7816");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t 7816");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static command_t CommandTable[] = {

View file

@ -118,7 +118,6 @@ static int print_barcode(uint8_t *barcode, const size_t barcode_len, bool verbos
return PM3_SUCCESS;
}
static int CmdHfThinFilmInfo(const char *Cmd) {
uint8_t cmdp = 0;
@ -226,9 +225,13 @@ static int CmdHfThinFilmSim(const char *Cmd) {
}
static int CmdHfThinFilmList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("thinfilm");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t thinfilm");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static command_t CommandTable[] = {

View file

@ -481,9 +481,13 @@ static int CmdHFTopazCmdRaw(const char *Cmd) {
}
static int CmdHFTopazList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("topaz");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t topaz");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static int CmdHelp(const char *Cmd);

View file

@ -13,6 +13,7 @@
#include "util.h"
#include "fileutils.h"
#include "util_posix.h" // msleep
#include "cliparser.h"
// Currently the largest pixel 880*528 only needs 58.08K bytes
#define WSMAPSIZE 60000
@ -90,23 +91,6 @@ static model_t models[] = {
static int CmdHelp(const char *Cmd);
static int usage_hf_waveshare_loadbmp(void) {
PrintAndLogEx(NORMAL, "Load BMP file to Waveshare NFC ePaper.");
PrintAndLogEx(NORMAL, "Usage: hf waveshare loadbmp [h] f <filename[.bmp]> m <model_nr> [s]");
PrintAndLogEx(NORMAL, " Options :");
PrintAndLogEx(NORMAL, " f <fn> : " _YELLOW_("filename[.bmp]") " to upload to tag");
PrintAndLogEx(NORMAL, " m <nr> : " _YELLOW_("model number") " of your tag");
PrintAndLogEx(NORMAL, " s : save dithered version in filename-[n].bmp, only for RGB BMP");
for (uint8_t i = 0; i < MEND; i++) {
PrintAndLogEx(NORMAL, " m %2i : %s", i, models[i].desc);
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf waveshare loadbmp m 0 f myfile"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int picture_bit_depth(const uint8_t *bmp, const size_t bmpsize, const uint8_t model_nr) {
if (bmpsize < sizeof(BMP_HEADER))
return PM3_ESOFT;
@ -138,9 +122,15 @@ static int read_bmp_bitmap(const uint8_t *bmp, const size_t bmpsize, uint8_t mod
uint8_t color_flag = pbmpheader->Color_1;
// Get BMP file data pointer
uint32_t offset = pbmpheader->offset;
uint16_t width = pbmpheader->BMP_Width;
uint16_t height = pbmpheader->BMP_Height;
if ((width + 8) * height > WSMAPSIZE * 8) {
PrintAndLogEx(WARNING, "The file is too large, aborting!");
return PM3_ESOFT;
}
uint16_t X, Y;
uint16_t Image_Width_Byte = (pbmpheader->BMP_Width % 8 == 0) ? (pbmpheader->BMP_Width / 8) : (pbmpheader->BMP_Width / 8 + 1);
uint16_t Image_Width_Byte = (width % 8 == 0) ? (width / 8) : (width / 8 + 1);
uint16_t Bmp_Width_Byte = (Image_Width_Byte % 4 == 0) ? Image_Width_Byte : ((Image_Width_Byte / 4 + 1) * 4);
*black = calloc(WSMAPSIZE, sizeof(uint8_t));
@ -148,10 +138,10 @@ static int read_bmp_bitmap(const uint8_t *bmp, const size_t bmpsize, uint8_t mod
return PM3_EMALLOC;
}
// Write data into RAM
for (Y = 0; Y < pbmpheader->BMP_Height; Y++) { // columns
for (Y = 0; Y < height; Y++) { // columns
for (X = 0; X < Bmp_Width_Byte; X++) { // lines
if ((X < Image_Width_Byte) && ((X + (pbmpheader->BMP_Height - Y - 1) * Image_Width_Byte) < WSMAPSIZE)) {
(*black)[X + (pbmpheader->BMP_Height - Y - 1) * Image_Width_Byte] = color_flag ? bmp[offset] : ~bmp[offset];
if ((X < Image_Width_Byte) && ((X + (height - Y - 1) * Image_Width_Byte) < WSMAPSIZE)) {
(*black)[X + (height - Y - 1) * Image_Width_Byte] = color_flag ? bmp[offset] : ~bmp[offset];
}
offset++;
}
@ -241,7 +231,7 @@ static void dither_rgb_inplace(int16_t *chanR, int16_t *chanG, int16_t *chanB, u
int16_t oldR = chanR[XX + Y * width];
int16_t oldG = chanG[XX + Y * width];
int16_t oldB = chanB[XX + Y * width];
uint8_t newR, newG, newB;
uint8_t newR = 0, newG = 0, newB = 0;
nearest_color(oldR, oldG, oldB, palette, palettelen, &newR, &newG, &newB);
chanR[XX + Y * width] = newR;
chanG[XX + Y * width] = newG;
@ -381,6 +371,10 @@ static int read_bmp_rgb(uint8_t *bmp, const size_t bmpsize, uint8_t model_nr, ui
uint32_t offset = pbmpheader->offset;
uint16_t width = pbmpheader->BMP_Width;
uint16_t height = pbmpheader->BMP_Height;
if ((width + 8) * height > WSMAPSIZE * 8) {
PrintAndLogEx(WARNING, "The file is too large, aborting!");
return PM3_ESOFT;
}
int16_t *chanR = calloc(width * height, sizeof(int16_t));
if (chanR == NULL) {
@ -565,7 +559,7 @@ static int transceive_blocking(uint8_t *txBuf, uint16_t txBufLen, uint8_t *rxBuf
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
if (resp.oldarg[0] > rxBufLen) {
PrintAndLogEx(WARNING, "Received %"PRIu32 " bytes, rxBuf too small (%u)", resp.oldarg[0], rxBufLen);
PrintAndLogEx(WARNING, "Received %"PRIu64 " bytes, rxBuf too small (%u)", resp.oldarg[0], rxBufLen);
memcpy(rxBuf, resp.data.asBytes, rxBufLen);
*actLen = rxBufLen;
return PM3_ESOFT;
@ -646,14 +640,23 @@ static int start_drawing_1in54B(uint8_t model_nr, uint8_t *black, uint8_t *red)
static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
uint8_t progress = 0;
uint8_t step0[2] = {0xcd, 0x0d};
uint8_t step1[3] = {0xcd, 0x00, 10}; //select e-paper type and reset e-paper 4:2.13inch e-Paper 7:2.9inch e-Paper 10:4.2inch e-Paper 14:7.5inch e-Paper
uint8_t step1[3] = {0xcd, 0x00, 10}; // select e-paper type and reset e-paper
// 4 :2.13inch e-Paper
// 7 :2.9inch e-Paper
// 10 :4.2inch e-Paper
// 14 :7.5inch e-Paper
uint8_t step2[2] = {0xcd, 0x01}; // e-paper normal mode type
uint8_t step3[2] = {0xcd, 0x02}; // e-paper config1
uint8_t step4[2] = {0xcd, 0x03}; // e-paper power on
uint8_t step5[2] = {0xcd, 0x05}; // e-paper config2
uint8_t step6[2] = {0xcd, 0x06}; // EDP load to main
uint8_t step7[2] = {0xcd, 0x07}; // Data preparation
uint8_t step8[123] = {0xcd, 0x08, 0x64}; //Data start command 2.13inch(0x10:Send 16 data at a time) 2.9inch(0x10:Send 16 data at a time) 4.2inch(0x64:Send 100 data at a time) 7.5inch(0x78:Send 120 data at a time)
uint8_t step8[123] = {0xcd, 0x08, 0x64}; // Data start command
// 2.13inch(0x10:Send 16 data at a time)
// 2.9inch(0x10:Send 16 data at a time)
// 4.2inch(0x64:Send 100 data at a time)
// 7.5inch(0x78:Send 120 data at a time)
uint8_t step9[2] = {0xcd, 0x18}; // e-paper power on
uint8_t step10[2] = {0xcd, 0x09}; // Refresh e-paper
uint8_t step11[2] = {0xcd, 0x0a}; // wait for ready
@ -963,53 +966,60 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) {
return PM3_SUCCESS;
}
static int CmdHF14AWSLoadBmp(const char *Cmd) {
char filename[FILE_PATH_SIZE] = {0};
uint8_t cmdp = 0;
bool errors = false;
size_t filenamelen = 0;
uint8_t model_nr = 0xff;
bool save_conversions = false;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_hf_waveshare_loadbmp();
case 'f':
filenamelen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
if (filenamelen > FILE_PATH_SIZE - 5)
filenamelen = FILE_PATH_SIZE - 5;
cmdp += 2;
break;
case 'm':
model_nr = param_get8(Cmd, cmdp + 1);
cmdp += 2;
break;
case 's':
save_conversions = true;
cmdp += 1;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp));
errors = true;
break;
}
char desc[800] = {0};
for (uint8_t i = 0; i < MEND; i++) {
snprintf(desc + strlen(desc),
sizeof(desc) - strlen(desc),
"hf waveshare loadbmp -f myfile -m %2u -> %s ( %u, %u )\n",
i,
models[i].desc,
models[i].width,
models[i].height
);
}
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf waveshare loadbmp",
"Load BMP file to Waveshare NFC ePaper.",
desc
);
char modeldesc[40];
snprintf(modeldesc, sizeof(modeldesc), "model number [0 - %u] of your tag", MEND - 1);
void *argtable[] = {
arg_param_begin,
arg_int1("m", NULL, "<nr>", modeldesc),
arg_lit0("s", "save", "save dithered version in filename-[n].bmp, only for RGB BMP"),
arg_str1("f", "file", "<filename>", "filename[.bmp] to upload to tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int model_nr = arg_get_int_def(ctx, 1, -1);
bool save_conversions = arg_get_lit(ctx, 2);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
//Validations
if (filenamelen < 1) {
if (fnlen < 1) {
PrintAndLogEx(WARNING, "Missing filename");
errors = true;
return PM3_EINVARG;
}
if (model_nr == 0xff) {
if (model_nr == -1) {
PrintAndLogEx(WARNING, "Missing model");
errors = true;
} else if (model_nr >= MEND) {
PrintAndLogEx(WARNING, "Unknown model");
errors = true;
return PM3_EINVARG;
}
if (model_nr >= MEND) {
PrintAndLogEx(WARNING, "Unknown model");
return PM3_EINVARG;
}
if (errors || cmdp == 0) return usage_hf_waveshare_loadbmp();
uint8_t *bmp = NULL;
uint8_t *black = NULL;
@ -1042,7 +1052,7 @@ static int CmdHF14AWSLoadBmp(const char *Cmd) {
free(bmp);
return PM3_ESOFT;
} else {
PrintAndLogEx(ERR, "Error, BMP color depth %i not supported", depth);
PrintAndLogEx(ERR, "Error, BMP color depth %i not supported. Must be 1 (BW) or 24 (RGB)", depth);
free(bmp);
return PM3_ESOFT;
}

View file

@ -15,6 +15,7 @@
#include <ctype.h>
#include "cmdparser.h" // command_t
#include "cliparser.h"
#include "comms.h"
#include "usart_defs.h"
#include "ui.h"
@ -515,6 +516,77 @@ static int CmdStatus(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdTearoff(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hw tearoff",
"Configure a tear-off hook for the next write command supporting tear-off\n"
"After having been triggered by a write command, the tear-off hook is deactivated\n"
"Delay (in us) must be between 1 and 43000 (43ms). Precision is about 1/3us.",
"hw tearoff --delay 1200 --> define delay of 1200us\n"
"hw tearoff --on --> (re)activate a previously defined delay\n"
"hw tearoff --off --> deactivate a previously activated but not yet triggered hook\n");
void *argtable[] = {
arg_param_begin,
arg_int0(NULL, "delay", "<dec>", "Delay in us before triggering tear-off, must be between 1 and 43000"),
arg_lit0(NULL, "on", "Activate tear-off hook"),
arg_lit0(NULL, "off", "Deactivate tear-off hook"),
arg_lit0("s", "silent", "less verbose output"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
struct {
uint16_t delay_us;
bool on;
bool off;
} PACKED params;
int delay = arg_get_int_def(ctx, 1, -1);
params.on = arg_get_lit(ctx, 2);
params.off = arg_get_lit(ctx, 3);
bool silent = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
if (delay != -1) {
if ((delay < 1) || (delay > 43000)) {
PrintAndLogEx(WARNING, "You can't set delay out of 1..43000 range!");
return PM3_EINVARG;
}
} else {
delay = 0; // will be ignored by ARM
}
params.delay_us = delay;
if (params.on && params.off) {
PrintAndLogEx(WARNING, "You can't set both --on and --off!");
return PM3_EINVARG;
}
clearCommandBuffer();
SendCommandNG(CMD_SET_TEAROFF, (uint8_t *)&params, sizeof(params));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_SET_TEAROFF, &resp, 500) == false) {
PrintAndLogEx(WARNING, "Tear-off command timeout.");
return PM3_ETIMEOUT;
}
if (resp.status == PM3_SUCCESS) {
if (params.delay_us > 0)
PrintAndLogEx(INFO, "Tear-off hook configured with delay of " _GREEN_("%i us"), params.delay_us);
if (params.on && silent == false)
PrintAndLogEx(INFO, "Tear-off hook " _GREEN_("enabled"));
if (params.off && silent == false)
PrintAndLogEx(INFO, "Tear-off hook " _RED_("disabled"));
return PM3_SUCCESS;
}
if (silent == false)
PrintAndLogEx(WARNING, "Tear-off command failed.");
return resp.status;
}
static int CmdTia(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
PrintAndLogEx(INFO, "Triggering new Timing Interval Acquisition (TIA)...");
@ -621,6 +693,7 @@ static command_t CommandTable[] = {
{"setmux", CmdSetMux, IfPm3Present, "Set the ADC mux to a specific value"},
{"standalone", CmdStandalone, IfPm3Present, "Jump to the standalone mode"},
{"status", CmdStatus, IfPm3Present, "Show runtime status information about the connected Proxmark3"},
{"tearoff", CmdTearoff, IfPm3Present, "Program a tearoff hook for the next command supporting tearoff"},
{"tia", CmdTia, IfPm3Present, "Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider"},
{"tune", CmdTune, IfPm3Present, "Measure antenna tuning"},
{"version", CmdVersion, IfPm3Present, "Show version information about the connected Proxmark3"},

View file

@ -36,7 +36,7 @@
#include "cmdlfidteck.h" // for idteck menu
#include "cmdlfio.h" // for ioprox menu
#include "cmdlfcotag.h" // for COTAG meny
#include "cmdlffdx.h" // for fdx-b menu
#include "cmdlffdxb.h" // for FDX-B menu
#include "cmdlfgallagher.h" // for GALLAGHER menu
#include "cmdlfguard.h" // for gproxii menu
#include "cmdlfindala.h" // for indala menu
@ -1195,7 +1195,7 @@ int CmdLFpskSim(const char *Cmd) {
if (clk == 0) clk = GetPskClock("", false);
PrintAndLogEx(INFO, "clk: %d", clk);
if (!carrier) carrier = GetPskCarrier("", false);
if (!carrier) carrier = GetPskCarrier(false);
PrintAndLogEx(INFO, "carrier: %d", carrier);
} else {
@ -1454,7 +1454,7 @@ int CmdLFfind(const char *Cmd) {
if (demodNexWatch(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NexWatch ID") " found!"); goto out;}
if (demodIndala(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;}
if (demodEM410x(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;}
if (demodFDX(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;}
if (demodFDXB(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;}
if (demodGuard(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; }
if (demodIdteck(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;}
if (demodJablotron(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;}
@ -1527,7 +1527,7 @@ static command_t CommandTable[] = {
{"awid", CmdLFAWID, AlwaysAvailable, "{ AWID RFIDs... }"},
{"cotag", CmdLFCOTAG, AlwaysAvailable, "{ COTAG CHIPs... }"},
{"em", CmdLFEM4X, AlwaysAvailable, "{ EM4X CHIPs & RFIDs... }"},
{"fdx", CmdLFFdx, AlwaysAvailable, "{ FDX-B RFIDs... }"},
{"fdxb", CmdLFFdxB, AlwaysAvailable, "{ FDX-B RFIDs... }"},
{"gallagher", CmdLFGallagher, AlwaysAvailable, "{ GALLAGHER RFIDs... }"},
{"gproxii", CmdLFGuard, AlwaysAvailable, "{ Guardall Prox II RFIDs... }"},
{"hid", CmdLFHID, AlwaysAvailable, "{ HID Prox RFIDs... }"},

View file

@ -30,6 +30,8 @@
#include "cmddata.h"
#include "cmdlf.h"
#include "lfdemod.h"
#include "generator.h"
#include "cliparser.h"
static uint64_t g_em410xid = 0;
@ -164,7 +166,7 @@ static int usage_lf_em4x05_write(void) {
PrintAndLogEx(NORMAL, "Usage: lf em 4x05_write [h] <address> <data> <pwd>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h - this help");
PrintAndLogEx(NORMAL, " address - memory address to write to. (0-15)");
PrintAndLogEx(NORMAL, " address - memory address to write to. (0-13, 99 for Protection Words)");
PrintAndLogEx(NORMAL, " data - data to write (hex)");
PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)");
PrintAndLogEx(NORMAL, "Examples:");
@ -731,25 +733,30 @@ static bool downloadSamplesEM(void) {
}
// em_demod
static bool doPreambleSearch(size_t *startIdx) {
static int doPreambleSearch(size_t *startIdx) {
// sanity check
if (DemodBufferLen < EM_PREAMBLE_LEN) {
PrintAndLogEx(DEBUG, "DEBUG: Error - EM4305 demodbuffer too small");
return false;
return PM3_ESOFT;
}
// set size to 20 to only test first 14 positions for the preamble
size_t size = (20 > DemodBufferLen) ? DemodBufferLen : 20;
// set size to 9 to only test first 3 positions for the preamble
// do not set it too long else an error preamble followed by 010 could be seen as success.
size_t size = (9 > DemodBufferLen) ? DemodBufferLen : 9;
*startIdx = 0;
// skip first two 0 bits as they might have been missed in the demod
uint8_t preamble[EM_PREAMBLE_LEN] = {0, 0, 1, 0, 1, 0};
if (!preambleSearchEx(DemodBuffer, preamble, EM_PREAMBLE_LEN, &size, startIdx, true)) {
uint8_t errpreamble[EM_PREAMBLE_LEN] = {0, 0, 0, 0, 0, 1};
if (!preambleSearchEx(DemodBuffer, errpreamble, EM_PREAMBLE_LEN, &size, startIdx, true)) {
PrintAndLogEx(DEBUG, "DEBUG: Error - EM4305 preamble not found :: %zu", *startIdx);
return false;
return PM3_ESOFT;
}
return true;
return PM3_EFAILED; // Error preamble found
}
return PM3_SUCCESS;
}
static bool detectFSK(void) {
@ -793,7 +800,7 @@ static bool detectPSK(void) {
// try manchester - NOTE: ST only applies to T55x7 tags.
static bool detectASK_MAN(void) {
bool stcheck = false;
if (ASKDemod_ext(0, 0, 0, 0, false, false, false, 1, &stcheck) != PM3_SUCCESS) {
if (ASKDemod_ext(0, 0, 50, 0, false, false, false, 1, &stcheck) != PM3_SUCCESS) {
PrintAndLogEx(DEBUG, "DEBUG: Error - EM: ASK/Manchester Demod failed");
return false;
}
@ -852,35 +859,72 @@ static int setDemodBufferEM(uint32_t *word, size_t idx) {
// FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE, NRZ
// should cover 90% of known used configs
// the rest will need to be manually demoded for now...
static int demodEM4x05resp(uint32_t *word) {
static int demodEM4x05resp(uint32_t *word, bool onlyPreamble) {
size_t idx = 0;
*word = 0;
if (detectASK_MAN() && doPreambleSearch(&idx))
return setDemodBufferEM(word, idx);
if (detectASK_BI() && doPreambleSearch(&idx))
return setDemodBufferEM(word, idx);
if (detectNRZ() && doPreambleSearch(&idx))
return setDemodBufferEM(word, idx);
if (detectFSK() && doPreambleSearch(&idx))
return setDemodBufferEM(word, idx);
bool found_err = false;
int res = PM3_SUCCESS;
do {
if (detectASK_MAN()) {
res = doPreambleSearch(&idx);
if (res == PM3_SUCCESS)
break;
if (res == PM3_EFAILED)
// go on, maybe it's false positive and another modulation will work
found_err = true;
}
if (detectASK_BI()) {
res = doPreambleSearch(&idx);
if (res == PM3_SUCCESS)
break;
if (res == PM3_EFAILED)
found_err = true;
}
if (detectNRZ()) {
res = doPreambleSearch(&idx);
if (res == PM3_SUCCESS)
break;
if (res == PM3_EFAILED)
found_err = true;
}
if (detectFSK()) {
res = doPreambleSearch(&idx);
if (res == PM3_SUCCESS)
break;
if (res == PM3_EFAILED)
found_err = true;
}
if (detectPSK()) {
if (doPreambleSearch(&idx))
return setDemodBufferEM(word, idx);
res = doPreambleSearch(&idx);
if (res == PM3_SUCCESS)
break;
if (res == PM3_EFAILED)
found_err = true;
psk1TOpsk2(DemodBuffer, DemodBufferLen);
if (doPreambleSearch(&idx))
return setDemodBufferEM(word, idx);
res = doPreambleSearch(&idx);
if (res == PM3_SUCCESS)
break;
if (res == PM3_EFAILED)
found_err = true;
}
if (found_err)
return PM3_EFAILED;
return PM3_ESOFT;
} while (0);
if (onlyPreamble)
return PM3_SUCCESS;
res = setDemodBufferEM(word, idx);
if (res == PM3_SUCCESS)
return res;
if (found_err)
return PM3_EFAILED;
return res;
}
//////////////// 4205 / 4305 commands
#include "util_posix.h" // msclock
static int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) {
int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) {
struct {
uint32_t password;
@ -903,20 +947,21 @@ static int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t
if (downloadSamplesEM() == false) {
return PM3_ESOFT;
}
return demodEM4x05resp(word);
return demodEM4x05resp(word, false);
}
static int CmdEM4x05Demod(const char *Cmd) {
// uint8_t ctmp = tolower(param_getchar(Cmd, 0));
// if (ctmp == 'h') return usage_lf_em4x05_demod();
uint32_t word = 0;
return demodEM4x05resp(&word);
uint32_t dummy = 0;
return demodEM4x05resp(&dummy, false);
}
static int CmdEM4x05Dump(const char *Cmd) {
uint8_t addr = 0;
uint32_t pwd = 0;
bool usePwd = false;
bool needReadPwd = true;
uint8_t cmdp = 0;
uint8_t bytes[4] = {0};
uint32_t data[16];
@ -946,40 +991,66 @@ static int CmdEM4x05Dump(const char *Cmd) {
}
int success = PM3_SUCCESS;
int status;
int status, status14, status15;
uint32_t lock_bits = 0x00; // no blocks locked
bool gotLockBits = false;
bool lockInPW2 = false;
uint32_t word = 0;
const char *info[] = {"Info/User", "UID", "Password", "User", "Config", "User", "User", "User", "User", "User", "User", "User", "User", "User", "Lock", "Lock"};
if (usePwd) {
// Test first if a password is required
status = EM4x05ReadWord_ext(14, pwd, false, &word);
if (status == PM3_SUCCESS) {
PrintAndLogEx(INFO, "Note that password doesn't seem to be needed");
needReadPwd = false;
}
}
PrintAndLogEx(NORMAL, "Addr | data | ascii |lck| info");
PrintAndLogEx(NORMAL, "-----+----------+-------+---+-----");
// To flag any blocks locked we need to read blocks 14 and 15 first
// dont swap endin until we get block lock flags.
status = EM4x05ReadWord_ext(14, pwd, usePwd, &word);
if (status != PM3_SUCCESS)
success = PM3_ESOFT; // If any error ensure fail is set so not to save invalid data
if (word != 0x00)
status14 = EM4x05ReadWord_ext(14, pwd, usePwd, &word);
if (status14 == PM3_SUCCESS) {
if (!usePwd)
needReadPwd = false;
if ((word & 0x00008000) != 0x00) {
lock_bits = word;
gotLockBits = true;
}
data[14] = word;
status = EM4x05ReadWord_ext(15, pwd, usePwd, &word);
if (status != PM3_SUCCESS)
} else {
success = PM3_ESOFT; // If any error ensure fail is set so not to save invalid data
if (word != 0x00) // assume block 15 is the current lock block
}
status15 = EM4x05ReadWord_ext(15, pwd, usePwd, &word);
if (status15 == PM3_SUCCESS) {
if ((word & 0x00008000) != 0x00) { // assume block 15 is the current lock block
lock_bits = word;
gotLockBits = true;
lockInPW2 = true;
}
data[15] = word;
} else {
success = PM3_ESOFT; // If any error ensure fail is set so not to save invalid data
}
uint32_t lockbit;
// Now read blocks 0 - 13 as we have 14 and 15
for (; addr < 14; addr++) {
lockbit = (lock_bits >> addr) & 1;
if (addr == 2) {
if (usePwd) {
if ((needReadPwd) && (success != PM3_ESOFT)) {
data[addr] = BSWAP_32(pwd);
num_to_bytes(pwd, 4, bytes);
PrintAndLogEx(NORMAL, " %02u | %08X | %s | %c | password", addr, pwd, sprint_ascii(bytes, 4), ((lock_bits >> addr) & 1) ? 'x' : ' ');
PrintAndLogEx(NORMAL, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]);
} else {
// The pwd is not needed for Login so we're not sure what's the actual content of that block
PrintAndLogEx(NORMAL, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]);
}
} else {
data[addr] = 0x00; // Unknown password, but not used to set to zeros
PrintAndLogEx(NORMAL, " 02 | | | | " _RED_("cannot read"));
PrintAndLogEx(NORMAL, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]);
}
} else {
// success &= EM4x05ReadWord_ext(addr, pwd, usePwd, &word);
@ -989,15 +1060,27 @@ static int CmdEM4x05Dump(const char *Cmd) {
data[addr] = BSWAP_32(word);
if (status == PM3_SUCCESS) {
num_to_bytes(word, 4, bytes);
PrintAndLogEx(NORMAL, " %02d | %08X | %s | %c |", addr, word, sprint_ascii(bytes, 4), ((lock_bits >> addr) & 1) ? 'x' : ' ');
PrintAndLogEx(NORMAL, " %02u | %08X | %s | %s | %s", addr, word, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]);
} else
PrintAndLogEx(NORMAL, " %02d | | | | " _RED_("Fail"), addr);
PrintAndLogEx(NORMAL, " %02u | | | | %-10s %s", addr, info[addr], status == PM3_EFAILED ? _RED_("read denied") : _RED_("read failed"));
}
}
// Print blocks 14 and 15
// Both lock bits are protected with bit idx 14 (special case)
PrintAndLogEx(NORMAL, " %02d | %08X | %s | %c | Lock", 14, data[14], sprint_ascii(bytes, 4), ((lock_bits >> 14) & 1) ? 'x' : ' ');
PrintAndLogEx(NORMAL, " %02d | %08X | %s | %c | Lock", 15, data[15], sprint_ascii(bytes, 4), ((lock_bits >> 14) & 1) ? 'x' : ' ');
addr = 14;
if (status14 == PM3_SUCCESS) {
lockbit = (lock_bits >> addr) & 1;
PrintAndLogEx(NORMAL, " %02u | %08X | %s | %s | %-10s %s", addr, data[addr], sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr], lockInPW2 ? "" : _GREEN_("active"));
} else {
PrintAndLogEx(NORMAL, " %02u | | | | %-10s %s", addr, info[addr], status14 == PM3_EFAILED ? _RED_("read denied") : _RED_("read failed"));
}
addr = 15;
if (status15 == PM3_SUCCESS) {
lockbit = (lock_bits >> 14) & 1; // beware lock bit of word15 is pr14
PrintAndLogEx(NORMAL, " %02u | %08X | %s | %s | %-10s %s", addr, data[addr], sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr], lockInPW2 ? _GREEN_("active") : "");
} else {
PrintAndLogEx(NORMAL, " %02u | | | | %-10s %s", addr, info[addr], status15 == PM3_EFAILED ? _RED_("read denied") : _RED_("read failed"));
}
// Update endian for files
data[14] = BSWAP_32(data[14]);
data[15] = BSWAP_32(data[15]);
@ -1027,22 +1110,24 @@ static int CmdEM4x05Read(const char *Cmd) {
pwd = param_get32ex(Cmd, 1, 0xFFFFFFFF, 16);
if (addr > 15) {
PrintAndLogEx(NORMAL, "Address must be between 0 and 15");
PrintAndLogEx(WARNING, "Address must be between 0 and 15");
return PM3_ESOFT;
}
if (pwd == 0xFFFFFFFF) {
PrintAndLogEx(NORMAL, "Reading address %02u", addr);
PrintAndLogEx(INFO, "Reading address %02u", addr);
} else {
usePwd = true;
PrintAndLogEx(NORMAL, "Reading address %02u | password %08X", addr, pwd);
PrintAndLogEx(INFO, "Reading address %02u using password %08X", addr, pwd);
}
uint32_t word = 0;
int status = EM4x05ReadWord_ext(addr, pwd, usePwd, &word);
if (status == PM3_SUCCESS)
PrintAndLogEx(NORMAL, "Address %02d | %08X - %s", addr, word, (addr > 13) ? "Lock" : "");
PrintAndLogEx(SUCCESS, "Address %02d | %08X - %s", addr, word, (addr > 13) ? "Lock" : "");
else if (status == PM3_EFAILED)
PrintAndLogEx(ERR, "Tag denied Read operation");
else
PrintAndLogEx(NORMAL, "Read Address %02d | " _RED_("Fail"), addr);
PrintAndLogEx(WARNING, "No answer from tag");
return status;
}
@ -1057,18 +1142,44 @@ static int CmdEM4x05Write(const char *Cmd) {
addr = param_get8ex(Cmd, 0, 50, 10);
data = param_get32ex(Cmd, 1, 0, 16);
pwd = param_get32ex(Cmd, 2, 0xFFFFFFFF, 16);
bool protectOperation = addr == 99; // will do better with cliparser...
if (addr > 15) {
PrintAndLogEx(NORMAL, "Address must be between 0 and 15");
if ((addr > 13) && (!protectOperation)) {
PrintAndLogEx(WARNING, "Address must be between 0 and 13");
return PM3_EINVARG;
}
if (pwd == 0xFFFFFFFF)
PrintAndLogEx(NORMAL, "Writing address %d data %08X", addr, data);
else {
if (pwd == 0xFFFFFFFF) {
if (protectOperation)
PrintAndLogEx(INFO, "Writing protection words data %08X", data);
else
PrintAndLogEx(INFO, "Writing address %d data %08X", addr, data);
} else {
usePwd = true;
PrintAndLogEx(NORMAL, "Writing address %d data %08X using password %08X", addr, data, pwd);
if (protectOperation)
PrintAndLogEx(INFO, "Writing protection words data %08X using password %08X", data, pwd);
else
PrintAndLogEx(INFO, "Writing address %d data %08X using password %08X", addr, data, pwd);
}
if (protectOperation) { // set Protect Words
struct {
uint32_t password;
uint32_t data;
uint8_t usepwd;
} PACKED payload;
payload.password = pwd;
payload.data = data;
payload.usepwd = usePwd;
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X_PROTECTWORD, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_EM4X_PROTECTWORD, &resp, 2000)) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT;
}
} else {
struct {
uint32_t password;
uint32_t data;
@ -1088,17 +1199,19 @@ static int CmdEM4x05Write(const char *Cmd) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT;
}
}
if (!downloadSamplesEM())
return PM3_ENODATA;
//need 0 bits demoded (after preamble) to verify write cmd
uint32_t dummy = 0;
int status = demodEM4x05resp(&dummy);
int status = demodEM4x05resp(&dummy, true);
if (status == PM3_SUCCESS)
PrintAndLogEx(SUCCESS, "Success writing to tag");
else if (status == PM3_EFAILED)
PrintAndLogEx(ERR, "Tag denied %s operation", protectOperation ? "Protect" : "Write");
else
PrintAndLogEx(DEBUG, "No answer from tag");
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05_read`") " to verify");
return status;
}
@ -1263,8 +1376,10 @@ static void printEM4x05config(uint32_t wordData) {
uint8_t disable = (wordData & EM4x05_DISABLE_ALLOWED) >> 23;
uint8_t rtf = (wordData & EM4x05_READER_TALK_FIRST) >> 24;
uint8_t pigeon = (wordData & (1 << 26)) >> 26;
PrintAndLogEx(INFO, "ConfigWord: %08X (Word 4)\n", wordData);
PrintAndLogEx(INFO, "Config Breakdown:");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Config Information") " ---------------------------");
PrintAndLogEx(INFO, "ConfigWord: %08X (Word 4)", wordData);
PrintAndLogEx(INFO, " Data Rate: %02u | "_YELLOW_("RF/%u"), wordData & 0x3F, datarate);
PrintAndLogEx(INFO, " Encoder: %u | " _YELLOW_("%s"), encoder, enc);
PrintAndLogEx(INFO, " PSK CF: %u | %s", PSKcf, cf);
@ -1277,30 +1392,50 @@ static void printEM4x05config(uint32_t wordData) {
PrintAndLogEx(INFO, " R.A.W.: %u | Read after write is %s", raw, raw ? "on" : "off");
PrintAndLogEx(INFO, " Disable: %u | Disable command is %s", disable, disable ? "accepted" : "not accepted");
PrintAndLogEx(INFO, " R.T.F.: %u | Reader talk first is %s", rtf, rtf ? _YELLOW_("enabled") : "disabled");
PrintAndLogEx(INFO, " Pigeon: %u | Pigeon mode is %s\n", pigeon, pigeon ? _YELLOW_("enabled") : "disabled");
PrintAndLogEx(INFO, " Pigeon: %u | Pigeon mode is %s", pigeon, pigeon ? _YELLOW_("enabled") : "disabled");
}
static void printEM4x05info(uint32_t block0, uint32_t serial) {
uint8_t chipType = (block0 >> 1) & 0xF;
uint8_t cap = (block0 >> 5) & 3;
uint16_t custCode = (block0 >> 9) & 0x3FF;
uint16_t custCode = (block0 >> 9) & 0x2FF;
PrintAndLogEx(INFO, " block0: %X", block0);
PrintAndLogEx(INFO, " chiptype: %X", chipType);
PrintAndLogEx(INFO, "capacitor: %X", cap);
PrintAndLogEx(INFO, " custcode: %X", custCode);
/* bits
// 0, rfu
// 1,2,3,4 chip type
// 5,6 resonant cap
// 7,8, rfu
// 9 - 18 customer code
// 19, rfu
98765432109876543210
001000000000
// 00100000000001111000
// 1100
// 011
// 00100000000
*/
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
char ctstr[50];
snprintf(ctstr, sizeof(ctstr), "\n Chip Type: %u | ", chipType);
snprintf(ctstr, sizeof(ctstr), " Chip Type: %u | ", chipType);
switch (chipType) {
case 9:
snprintf(ctstr + strlen(ctstr), sizeof(ctstr) - strlen(ctstr), _YELLOW_("%s"), "EM4305");
break;
case 4:
snprintf(ctstr + strlen(ctstr), sizeof(ctstr) - strlen(ctstr), _YELLOW_("%s"), "EM4469");
break;
case 8:
snprintf(ctstr + strlen(ctstr), sizeof(ctstr) - strlen(ctstr), _YELLOW_("%s"), "EM4205");
break;
case 4:
snprintf(ctstr + strlen(ctstr), sizeof(ctstr) - strlen(ctstr), _YELLOW_("%s"), "Unknown");
break;
case 2:
snprintf(ctstr + strlen(ctstr), sizeof(ctstr) - strlen(ctstr), _YELLOW_("%s"), "EM4469");
break;
//add more here when known
default:
snprintf(ctstr + strlen(ctstr), sizeof(ctstr) - strlen(ctstr), _YELLOW_("%s"), "Unknown");
@ -1328,14 +1463,17 @@ static void printEM4x05info(uint32_t block0, uint32_t serial) {
PrintAndLogEx(SUCCESS, " Cust Code: %03u | %s", custCode, (custCode == 0x200) ? "Default" : "Unknown");
if (serial != 0)
PrintAndLogEx(SUCCESS, "\n Serial #: " _YELLOW_("%08X"), serial);
PrintAndLogEx(SUCCESS, " Serial #: " _YELLOW_("%08X"), serial);
}
static void printEM4x05ProtectionBits(uint32_t word) {
static void printEM4x05ProtectionBits(uint32_t word, uint8_t addr) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Protection") " ---------------------------");
PrintAndLogEx(INFO, "ProtectionWord: %08X (Word %i)", word, addr);
for (uint8_t i = 0; i < 15; i++) {
PrintAndLogEx(INFO, " Word: %02u | %s", i, (((1 << i) & word) || i < 2) ? _RED_("write Locked") : "unlocked");
PrintAndLogEx(INFO, " Word: %02u | %s", i, ((1 << i) & word) ? _RED_("write Locked") : "unlocked");
if (i == 14)
PrintAndLogEx(INFO, " Word: %02u | %s", i + 1, (((1 << i) & word) || i < 2) ? _RED_("write locked") : "unlocked");
PrintAndLogEx(INFO, " Word: %02u | %s", i + 1, ((1 << i) & word) ? _RED_("write locked") : "unlocked");
}
}
@ -1382,18 +1520,126 @@ static int CmdEM4x05Info(const char *Cmd) {
if (EM4x05ReadWord_ext(EM_PROT1_BLOCK, pwd, usePwd, &word) != PM3_SUCCESS) {
return PM3_ESOFT;
}
// if status bit says this is not the used protection word
if (!(word & 0x8000)) {
if (word & 0x8000) {
printEM4x05ProtectionBits(word, EM_PROT1_BLOCK);
return PM3_SUCCESS;
} else { // if status bit says this is not the used protection word
if (EM4x05ReadWord_ext(EM_PROT2_BLOCK, pwd, usePwd, &word) != PM3_SUCCESS)
return PM3_ESOFT;
if (word & 0x8000) {
printEM4x05ProtectionBits(word, EM_PROT2_BLOCK);
return PM3_SUCCESS;
}
}
//something went wrong
return PM3_ESOFT;
}
//something went wrong
if (!(word & 0x8000))
static bool is_cancelled(void) {
if (kbd_enter_pressed()) {
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
return true;
}
return false;
}
// load a default pwd file.
static int CmdEM4x05Chk(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 4x05_chk",
"This command uses a dictionary attack against EM4205/4305/4469/4569",
"lf em 4x05_chk\n"
"lf em 4x05_chk -e 0x00000022B8 -> remember to use 0x for hex\n"
"lf em 4x05_chk -f t55xx_default_pwds -> use T55xx default dictionary"
);
void *argtable[] = {
arg_param_begin,
arg_strx0("f", "file", "<*.dic>", "loads a default keys dictionary file <*.dic>"),
arg_u64_0("e", "em", "<EM4100>", "try the calculated password from some cloners based on EM4100 ID"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
uint64_t card_id = arg_get_u64_def(ctx, 2, 0);
CLIParserFree(ctx);
if (strlen(filename) == 0) {
snprintf(filename, sizeof(filename), "t55xx_default_pwds");
}
PrintAndLogEx(NORMAL, "");
uint8_t addr = 4;
uint32_t word = 0;
bool found = false;
uint64_t t1 = msclock();
// White cloner password based on EM4100 ID
if ( card_id > 0 ) {
uint32_t pwd = lf_t55xx_white_pwdgen(card_id & 0xFFFFFFFF);
PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", pwd);
int status = EM4x05ReadWord_ext(addr, pwd, true, &word);
if (status == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd);
found = true;
}
}
// Loop dictionary
uint8_t *keyBlock = NULL;
if (found == false) {
PrintAndLogEx(INFO, "press " _YELLOW_("'enter'") " to cancel the command");
word = 0;
uint32_t keycount = 0;
int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount);
if (res != PM3_SUCCESS || keycount == 0 || keyBlock == NULL) {
PrintAndLogEx(WARNING, "no keys found in file");
if (keyBlock != NULL)
free(keyBlock);
return PM3_ESOFT;
}
printEM4x05ProtectionBits(word);
for (uint32_t c = 0; c < keycount; ++c) {
if (!session.pm3_present) {
PrintAndLogEx(WARNING, "device offline\n");
free(keyBlock);
return PM3_ENODATA;
}
if (is_cancelled()) {
free(keyBlock);
return PM3_EOPABORTED;
}
uint32_t curr_password = bytes_to_num(keyBlock + 4 * c, 4);
PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password);
int status = EM4x05ReadWord_ext(addr, curr_password, 1, &word);
if (status == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", curr_password);
found = true;
break;
}
}
}
if (found == false)
PrintAndLogEx(WARNING, "check pwd failed");
free(keyBlock);
t1 = msclock() - t1;
PrintAndLogEx(SUCCESS, "\ntime in check pwd " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
return PM3_SUCCESS;
}
@ -1409,6 +1655,7 @@ static command_t CommandTable[] = {
{"410x_spoof", CmdEM410xWatchnSpoof, IfPm3Lf, "watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
{"410x_clone", CmdEM410xClone, IfPm3Lf, "write EM410x UID to T55x7 or Q5/T5555 tag"},
{"----------", CmdHelp, AlwaysAvailable, "-------------------- " _CYAN_("EM 4x05 / 4x69") " -------------------"},
{"4x05_chk", CmdEM4x05Chk, IfPm3Lf, "Check passwords from dictionary"},
{"4x05_demod", CmdEM4x05Demod, AlwaysAvailable, "demodulate a EM4x05/EM4x69 tag from the GraphBuffer"},
{"4x05_dump", CmdEM4x05Dump, IfPm3Lf, "dump EM4x05/EM4x69 tag"},
{"4x05_wipe", CmdEM4x05Wipe, IfPm3Lf, "wipe EM4x05/EM4x69 tag"},

View file

@ -17,6 +17,7 @@ int CmdLFEM4X(const char *Cmd);
int demodEM410x(bool verbose);
bool EM4x05IsBlock0(uint32_t *word);
int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word);
void printEM410x(uint32_t hi, uint64_t id);
int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo);

View file

@ -93,7 +93,7 @@ static int usage_lf_em4x50_wipe(void) {
PrintAndLogEx(NORMAL, " h - this help");
PrintAndLogEx(NORMAL, " p <pwd> - password (hex)");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_wwipe p 11223344"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_wipe p 11223344"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}

View file

@ -8,7 +8,7 @@
// Differential Biphase, rf/32, 128 bits (known)
//-----------------------------------------------------------------------------
#include "cmdlffdx.h"
#include "cmdlffdxb.h"
#include <inttypes.h>
#include <string.h>
@ -48,9 +48,9 @@
static int CmdHelp(const char *Cmd);
static int usage_lf_fdx_clone(void) {
static int usage_lf_fdxb_clone(void) {
PrintAndLogEx(NORMAL, "Clone a FDX-B animal tag to a T55x7 or Q5/T5555 tag.");
PrintAndLogEx(NORMAL, "Usage: lf fdx clone [h] [c <country code>] [a <national code>] [e <extended>] <s> <Q5>");
PrintAndLogEx(NORMAL, "Usage: lf fdxb clone [h] [c <country code>] [a <national code>] [e <extended>] <s> <Q5>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " c <country> : (dec) Country code");
@ -60,15 +60,15 @@ static int usage_lf_fdx_clone(void) {
PrintAndLogEx(NORMAL, " <Q5> : Specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone c 999 n 112233 s"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone c 999 n 112233 e 16a"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdxb clone c 999 n 112233 s"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdxb clone c 999 n 112233 e 16a"));
return PM3_SUCCESS;
}
static int usage_lf_fdx_read(void) {
static int usage_lf_fdxb_read(void) {
PrintAndLogEx(NORMAL, "Read FDX-B animal tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf fdx read [h] [@]");
PrintAndLogEx(NORMAL, "Usage: lf fdxb read [h] [@]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " @ : run continuously until a key is pressed (optional)");
@ -76,11 +76,11 @@ static int usage_lf_fdx_read(void) {
return PM3_SUCCESS;
}
static int usage_lf_fdx_sim(void) {
static int usage_lf_fdxb_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of FDX-B animal tag");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf fdx sim [h] [c <country code>] [n <national code>] [e <extended>] <s> <Q5>");
PrintAndLogEx(NORMAL, "Usage: lf fdxb sim [h] [c <country code>] [n <national code>] [e <extended>] <s> <Q5>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " c <country> : (dec) Country code");
@ -90,8 +90,8 @@ static int usage_lf_fdx_sim(void) {
PrintAndLogEx(NORMAL, " <Q5> : Specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx sim c 999 n 112233 s"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx sim c 999 n 112233 e 16a"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdxb sim c 999 n 112233 s"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdxb sim c 999 n 112233 e 16a"));
return PM3_SUCCESS;
}
@ -215,9 +215,275 @@ static int CmdFDXBdemodBI(const char *Cmd) {
}
*/
// For the country part:
// wget -q -O - "https://en.wikipedia.org/w/index.php?title=List_of_ISO_3166_country_codes&action=raw" | awk '/id=/{match($0, /\[\[([^\]|]*)/, a); name=a[1];getline;getline;getline;getline;getline;match($0, /numeric#([0-9]*)/, a);num=a[1]; if (num != "") {printf " { %3u, \"%s\" },\n", num, name}}'
// Beware the bottom of the list contains also Manufacturers list
const fdxbCountryMapping_t fdxbCountryMapping[] = {
{ 4, "Afghanistan" },
{ 8, "Albania" },
{ 12, "Algeria" },
{ 16, "American Samoa" },
{ 20, "Andorra" },
{ 24, "Angola" },
{ 660, "Anguilla" },
{ 10, "Antarctica" },
{ 28, "Antigua and Barbuda" },
{ 32, "Argentina" },
{ 51, "Armenia" },
{ 533, "Aruba" },
{ 40, "Austria" },
{ 31, "Azerbaijan" },
{ 44, "The Bahamas" },
{ 48, "Bahrain" },
{ 50, "Bangladesh" },
{ 52, "Barbados" },
{ 112, "Belarus" },
{ 56, "Belgium" },
{ 84, "Belize" },
{ 204, "Benin" },
{ 60, "Bermuda" },
{ 64, "Bhutan" },
{ 68, "Bolivia" },
{ 535, "Bonaire" },
{ 70, "Bosnia and Herzegovina" },
{ 72, "Botswana" },
{ 74, "Bouvet Island" },
{ 76, "Brazil" },
{ 86, "British Indian Ocean Territory" },
{ 100, "Bulgaria" },
{ 854, "Burkina Faso" },
{ 132, "Cape Verde" },
{ 116, "Cambodia" },
{ 120, "Cameroon" },
{ 124, "Canada" },
{ 140, "Central African Republic" },
{ 148, "Chad" },
{ 152, "Chile" },
{ 156, "China" },
{ 170, "Colombia" },
{ 174, "Comoros" },
{ 180, "Democratic Republic of the Congo" },
{ 178, "Republic of the Congo" },
{ 184, "Cook Islands" },
{ 384, "Ivory Coast" },
{ 191, "Croatia" },
{ 192, "Cuba" },
{ 531, "Curaçao" },
{ 196, "Cyprus" },
{ 203, "Czech Republic" },
{ 262, "Djibouti" },
{ 212, "Dominica" },
{ 214, "Dominican Republic" },
{ 818, "Egypt" },
{ 222, "El Salvador" },
{ 232, "Eritrea" },
{ 233, "Estonia" },
{ 748, "Eswatini" },
{ 231, "Ethiopia" },
{ 238, "Falkland Islands" },
{ 234, "Faroe Islands" },
{ 242, "Fiji" },
{ 246, "Finland" },
{ 250, "France" },
{ 254, "French Guiana" },
{ 258, "French Polynesia" },
{ 260, "French Southern Territories" },
{ 266, "Gabon" },
{ 270, "The Gambia" },
{ 268, "Georgia (country)" },
{ 276, "Germany" },
{ 288, "Ghana" },
{ 292, "Gibraltar" },
{ 304, "Greenland" },
{ 308, "Grenada" },
{ 312, "Guadeloupe" },
{ 316, "Guam" },
{ 320, "Guatemala" },
{ 831, "Bailiwick of Guernsey" },
{ 324, "Guinea" },
{ 624, "Guinea-Bissau" },
{ 328, "Guyana" },
{ 332, "Haiti" },
{ 336, "Holy See" },
{ 340, "Honduras" },
{ 344, "Hong Kong" },
{ 348, "Hungary" },
{ 352, "Iceland" },
{ 356, "India" },
{ 360, "Indonesia" },
{ 364, "Iran (Islamic Republic of)" },
{ 368, "Iraq" },
{ 372, "Republic of Ireland" },
{ 833, "Isle of Man" },
{ 376, "Israel" },
{ 380, "Italy" },
{ 832, "Jersey" },
{ 400, "Jordan" },
{ 398, "Kazakhstan" },
{ 404, "Kenya" },
{ 296, "Kiribati" },
{ 408, "North Korea" },
{ 410, "South Korea" },
{ 414, "Kuwait" },
{ 417, "Kyrgyzstan" },
{ 418, "Laos" },
{ 428, "Latvia" },
{ 422, "Lebanon" },
{ 426, "Lesotho" },
{ 430, "Liberia" },
{ 434, "Libya" },
{ 438, "Liechtenstein" },
{ 440, "Lithuania" },
{ 442, "Luxembourg" },
{ 446, "Macau" },
{ 807, "North Macedonia" },
{ 450, "Madagascar" },
{ 454, "Malawi" },
{ 458, "Malaysia" },
{ 462, "Maldives" },
{ 466, "Mali" },
{ 470, "Malta" },
{ 584, "Marshall Islands" },
{ 474, "Martinique" },
{ 478, "Mauritania" },
{ 480, "Mauritius" },
{ 175, "Mayotte" },
{ 484, "Mexico" },
{ 583, "Federated States of Micronesia" },
{ 498, "Moldova" },
{ 492, "Monaco" },
{ 496, "Mongolia" },
{ 499, "Montenegro" },
{ 500, "Montserrat" },
{ 504, "Morocco" },
{ 508, "Mozambique" },
{ 104, "Myanmar" },
{ 516, "Namibia" },
{ 520, "Nauru" },
{ 524, "Nepal" },
{ 528, "Kingdom of the Netherlands" },
{ 540, "New Caledonia" },
{ 554, "New Zealand" },
{ 558, "Nicaragua" },
{ 562, "Niger" },
{ 566, "Nigeria" },
{ 570, "Niue" },
{ 574, "Norfolk Island" },
{ 578, "Norway" },
{ 512, "Oman" },
{ 586, "Pakistan" },
{ 585, "Palau" },
{ 275, "State of Palestine" },
{ 591, "Panama" },
{ 598, "Papua New Guinea" },
{ 600, "Paraguay" },
{ 608, "Philippines" },
{ 612, "Pitcairn Islands" },
{ 616, "Poland" },
{ 620, "Portugal" },
{ 630, "Puerto Rico" },
{ 634, "Qatar" },
{ 638, "Réunion" },
{ 642, "Romania" },
{ 643, "Russia" },
{ 646, "Rwanda" },
{ 654, "Saint Helena" },
{ 659, "Saint Kitts and Nevis" },
{ 662, "Saint Lucia" },
{ 663, "Collectivity of Saint Martin" },
{ 666, "Saint Pierre and Miquelon" },
{ 670, "Saint Vincent and the Grenadines" },
{ 882, "Samoa" },
{ 674, "San Marino" },
{ 678, "São Tomé and Príncipe" },
{ 682, "Saudi Arabia" },
{ 688, "Serbia" },
{ 690, "Seychelles" },
{ 694, "Sierra Leone" },
{ 702, "Singapore" },
{ 703, "Slovakia" },
{ 705, "Slovenia" },
{ 90, "Solomon Islands" },
{ 706, "Somalia" },
{ 710, "South Africa" },
{ 239, "South Georgia and the South Sandwich Islands" },
{ 724, "Spain" },
{ 144, "Sri Lanka" },
{ 729, "Sudan" },
{ 740, "Suriname" },
{ 744, "Svalbard" },
{ 752, "Sweden" },
{ 756, "Switzerland" },
{ 760, "Syria" },
{ 158, "Taiwan" },
{ 762, "Tajikistan" },
{ 834, "Tanzania" },
{ 764, "Thailand" },
{ 626, "East Timor" },
{ 768, "Togo" },
{ 772, "Tokelau" },
{ 776, "Tonga" },
{ 780, "Trinidad and Tobago" },
{ 788, "Tunisia" },
{ 792, "Turkey" },
{ 795, "Turkmenistan" },
{ 796, "Turks and Caicos Islands" },
{ 798, "Tuvalu" },
{ 800, "Uganda" },
{ 804, "Ukraine" },
{ 784, "United Arab Emirates" },
{ 826, "United Kingdom" },
{ 581, "United States Minor Outlying Islands" },
{ 840, "United States" },
{ 860, "Uzbekistan" },
{ 548, "Vanuatu" },
{ 704, "Vietnam" },
{ 92, "British Virgin Islands" },
{ 850, "United States Virgin Islands" },
{ 732, "Western Sahara" },
{ 887, "Yemen" },
{ 894, "Zambia" },
{ 716, "Zimbabwe" },
// Manufacturers list:
{ 952, "JECTA" },
{ 953, "Cromasa Identificacion electronica S.A."},
{ 955, "Reseaumatique" },
{ 956, "Trovan Ltd. (ACK Reunite)" },
{ 958, "Pet ID" },
{ 959, "Global ID Technologies" },
{ 961, "Mannings I.A.I.D." },
{ 963, "Korth Eletro Mecanica LTDA" },
{ 965, "4D Technology Co. Ltd" },
{ 966, "PetCode" },
{ 967, "Rfdynamics / M4S ID in Canada" },
{ 968, "AEG / EIDAP in Canada" },
{ 972, "Planet ID" },
{ 975, "Sokymat" },
{ 977, "AVID" },
{ 978, "Ordicam" },
{ 981, "Microfindr, Datamars, Found Animals, Crystal Tag, Banfield, Bayer resQ, Peeva" },
{ 982, "24 Pet Watch (Allflex)" },
{ 985, "HomeAgain (Destron Fearing/Digital Angel)" },
{ 991, "Peeva" },
{ 999, "Test range" },
{ 0, "N/A" } // must be the last entry
};
static const char* mapFDBX(uint16_t countryCode) {
uint16_t i = 0;
while (fdxbCountryMapping[i].code > 0) {
if (countryCode == fdxbCountryMapping[i].code) {
return fdxbCountryMapping[i].desc;
}
i++;
}
return fdxbCountryMapping[i].desc;
}
//see ASKDemod for what args are accepted
//almost the same demod as cmddata.c/CmdFDXBdemodBI
int demodFDX(bool verbose) {
int demodFDXB(bool verbose) {
//Differential Biphase / di-phase (inverted biphase)
//get binary from ask wave
if (ASKbiphaseDemod(0, 32, 1, 100, false) != PM3_SUCCESS) {
@ -253,18 +519,34 @@ int demodFDX(bool verbose) {
//got a good demod
uint8_t offset;
// ISO: bits 27..64
uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(DemodBuffer + 32, 6)) << 32) | bytebits_to_byteLSBF(DemodBuffer, 32);
offset = 38;
// ISO: bits 17..26
uint16_t countryCode = bytebits_to_byteLSBF(DemodBuffer + offset, 10);
offset += 10;
// ISO: bits 16
uint8_t dataBlockBit = DemodBuffer[offset];
offset++;
uint32_t reservedCode = bytebits_to_byteLSBF(DemodBuffer + offset, 14);
// ISO: bits 15
uint8_t rudiBit = DemodBuffer[offset];
offset += 14;
offset++;
// ISO: bits 10..14
uint32_t reservedCode = bytebits_to_byteLSBF(DemodBuffer + offset, 5);
offset += 5;
// ISO: bits 5..9
uint32_t userInfo = bytebits_to_byteLSBF(DemodBuffer + offset, 5);
offset += 5;
// ISO: bits 2..4
uint32_t replacementNr = bytebits_to_byteLSBF(DemodBuffer + offset, 3);
offset += 3;
uint8_t animalBit = DemodBuffer[offset];
offset++;
@ -283,12 +565,15 @@ int demodFDX(bool verbose) {
return PM3_SUCCESS;
}
PrintAndLogEx(SUCCESS, "FDX-B / ISO 11784/5 Animal");
PrintAndLogEx(SUCCESS, "Animal ID " _GREEN_("%04u-%012"PRIu64), countryCode, NationalCode);
PrintAndLogEx(SUCCESS, "Animal ID " _GREEN_("%03u-%012"PRIu64), countryCode, NationalCode);
PrintAndLogEx(SUCCESS, "National Code " _GREEN_("%012" PRIu64) " (0x%" PRIX64 ")", NationalCode, NationalCode);
PrintAndLogEx(SUCCESS, "Country Code " _GREEN_("%04u"), countryCode);
PrintAndLogEx(SUCCESS, "Country Code " _GREEN_("%03u") " - %s", countryCode, mapFDBX(countryCode));
PrintAndLogEx(SUCCESS, "Reserved/RFU %u (0x%04X)", reservedCode, reservedCode);
PrintAndLogEx(SUCCESS, " Animal bit set? %s", animalBit ? _YELLOW_("True") : "False");
PrintAndLogEx(SUCCESS, " Data block? %s [value 0x%X]", dataBlockBit ? _YELLOW_("True") : "False", extended);
PrintAndLogEx(SUCCESS, " RUDI bit? %s", rudiBit ? _YELLOW_("True") " (advanced transponder)" : "False");
PrintAndLogEx(SUCCESS, " User Info? %u %s", userInfo, userInfo == 0 ? "(RFU)":"");
PrintAndLogEx(SUCCESS, " Replacement No? %u %s", replacementNr, replacementNr == 0 ? "(RFU)":"");
uint8_t c[] = {0, 0};
compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]);
@ -321,12 +606,12 @@ int demodFDX(bool verbose) {
return PM3_SUCCESS;
}
static int CmdFdxDemod(const char *Cmd) {
static int CmdFdxBDemod(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
return demodFDX(true);
return demodFDXB(true);
}
static int CmdFdxRead(const char *Cmd) {
static int CmdFdxBRead(const char *Cmd) {
sample_config config;
memset(&config, 0, sizeof(sample_config));
int retval = lf_getconfig(&config);
@ -341,7 +626,7 @@ static int CmdFdxRead(const char *Cmd) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_fdx_read();
return usage_lf_fdxb_read();
case '@':
continuous = true;
cmdp++;
@ -354,7 +639,7 @@ static int CmdFdxRead(const char *Cmd) {
}
//Validations
if (errors) return usage_lf_fdx_read();
if (errors) return usage_lf_fdxb_read();
int16_t tmp_div = config.divisor;
if (tmp_div != LF_DIVISOR_134) {
config.divisor = LF_DIVISOR_134;
@ -375,7 +660,7 @@ static int CmdFdxRead(const char *Cmd) {
PrintAndLogEx(ERR, "failed to get LF read from device");
return retval;
}
ret = demodFDX(!continuous); // be verbose only if not in continuous mode
ret = demodFDXB(!continuous); // be verbose only if not in continuous mode
if (kbd_enter_pressed()) {
break;
}
@ -392,7 +677,7 @@ static int CmdFdxRead(const char *Cmd) {
return ret;
}
static int CmdFdxClone(const char *Cmd) {
static int CmdFdxBClone(const char *Cmd) {
uint32_t country_code = 0, extended = 0;
uint64_t national_code = 0;
@ -402,7 +687,7 @@ static int CmdFdxClone(const char *Cmd) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_fdx_clone();
return usage_lf_fdxb_clone();
case 'c': {
country_code = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
@ -436,7 +721,7 @@ static int CmdFdxClone(const char *Cmd) {
}
}
}
if (errors || strlen(Cmd) == 0) return usage_lf_fdx_clone();
if (errors || strlen(Cmd) == 0) return usage_lf_fdxb_clone();
verify_values(&national_code, &country_code, &extended, &is_animal);
@ -448,7 +733,7 @@ static int CmdFdxClone(const char *Cmd) {
PrintAndLogEx(INFO, " RFU 0");
uint8_t *bits = calloc(128, sizeof(uint8_t));
if (getFDXBits(national_code, country_code, is_animal, has_extended, extended, bits) != PM3_SUCCESS) {
if (getFDXBBits(national_code, country_code, is_animal, has_extended, extended, bits) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
free(bits);
return PM3_ESOFT;
@ -473,11 +758,11 @@ static int CmdFdxClone(const char *Cmd) {
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf fdx read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf fdxb read`") " to verify");
return res;
}
static int CmdFdxSim(const char *Cmd) {
static int CmdFdxBSim(const char *Cmd) {
uint32_t country_code = 0, extended = 0;
uint64_t national_code = 0;
@ -487,7 +772,7 @@ static int CmdFdxSim(const char *Cmd) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_fdx_sim();
return usage_lf_fdxb_sim();
case 'c': {
country_code = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
@ -516,7 +801,7 @@ static int CmdFdxSim(const char *Cmd) {
}
}
}
if (errors) return usage_lf_fdx_sim();
if (errors) return usage_lf_fdxb_sim();
verify_values(&national_code, &country_code, &extended, &is_animal);
@ -530,7 +815,7 @@ static int CmdFdxSim(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Simulating FDX-B animal ID: " _GREEN_("%04u-%"PRIu64), country_code, national_code);
uint8_t *bits = calloc(128, sizeof(uint8_t));
if (getFDXBits(national_code, country_code, is_animal, (extended > 0), extended, bits) != PM3_SUCCESS) {
if (getFDXBBits(national_code, country_code, is_animal, (extended > 0), extended, bits) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
free(bits);
return PM3_ESOFT;
@ -562,10 +847,10 @@ static int CmdFdxSim(const char *Cmd) {
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "this help"},
{"demod", CmdFdxDemod, AlwaysAvailable, "demodulate a FDX-B ISO11784/85 tag from the GraphBuffer"},
{"read", CmdFdxRead, IfPm3Lf, "attempt to read at 134kHz and extract tag data"},
{"clone", CmdFdxClone, IfPm3Lf, "clone animal ID tag to T55x7 or Q5/T5555"},
{"sim", CmdFdxSim, IfPm3Lf, "simulate Animal ID tag"},
{"demod", CmdFdxBDemod, AlwaysAvailable, "demodulate a FDX-B ISO11784/85 tag from the GraphBuffer"},
{"read", CmdFdxBRead, IfPm3Lf, "attempt to read at 134kHz and extract tag data"},
{"clone", CmdFdxBClone, IfPm3Lf, "clone animal ID tag to T55x7 or Q5/T5555"},
{"sim", CmdFdxBSim, IfPm3Lf, "simulate Animal ID tag"},
{NULL, NULL, NULL, NULL}
};
@ -575,7 +860,7 @@ static int CmdHelp(const char *Cmd) {
return PM3_SUCCESS;
}
int CmdLFFdx(const char *Cmd) {
int CmdLFFdxB(const char *Cmd) {
clearCommandBuffer();
return CmdsParse(CommandTable, Cmd);
}
@ -589,12 +874,12 @@ int detectFDXB(uint8_t *dest, size_t *size) {
uint8_t preamble[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx))
return -2; //preamble not found
if (*size != 128) return -3; //wrong demoded size
if (*size < 128) return -3; //wrong demoded size
//return start position
return (int)startIdx;
}
int getFDXBits(uint64_t national_code, uint16_t country_code, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits) {
int getFDXBBits(uint64_t national_code, uint16_t country_code, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits) {
// add preamble ten 0x00 and one 0x01
memset(bits, 0x00, 10);
@ -634,7 +919,7 @@ int getFDXBits(uint64_t national_code, uint16_t country_code, uint8_t is_animal,
raw[i] = bytebits_to_byte(bits + 11 + i * 9, 8);
init_table(CRC_11784);
uint16_t crc = crc16_fdx(raw, 8);
uint16_t crc = crc16_fdxb(raw, 8);
num_to_bytebitsLSBF(crc >> 0, 8, bits + 83);
num_to_bytebitsLSBF(crc >> 8, 8, bits + 92);

View file

@ -6,15 +6,20 @@
//-----------------------------------------------------------------------------
// Low frequency fdx-b tag commands
//-----------------------------------------------------------------------------
#ifndef CMDLFFDX_H__
#define CMDLFFDX_H__
#ifndef CMDLFFDXB_H__
#define CMDLFFDXB_H__
#include "common.h"
int CmdLFFdx(const char *Cmd);
typedef struct {
uint16_t code;
const char *desc;
} fdxbCountryMapping_t;
int CmdLFFdxB(const char *Cmd);
int detectFDXB(uint8_t *dest, size_t *size);
int demodFDX(bool verbose);
int getFDXBits(uint64_t national_code, uint16_t country_code, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits);
int demodFDXB(bool verbose);
int getFDXBBits(uint64_t national_code, uint16_t country_code, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits);
#endif

View file

@ -37,6 +37,7 @@
#include "util_posix.h"
#include "lfdemod.h"
#include "wiegand_formats.h"
#include "wiegand_formatutils.h"
#ifndef BITS
# define BITS 96
@ -135,61 +136,8 @@ int demodHID(bool verbose) {
return PM3_ESOFT;
}
if (hi2 != 0) { //extra large HID tags
PrintAndLogEx(SUCCESS, "HID Prox - " _GREEN_("%x%08x%08x (%u)"), hi2, hi, lo, (lo >> 1) & 0xFFFF);
} else { //standard HID tags <38 bits
uint8_t fmtLen = 0;
uint32_t cc = 0;
uint32_t fc = 0;
uint32_t cardnum = 0;
uint8_t oem = 0;
if (((hi >> 5) & 1) == 1) {//if bit 38 is set then < 37 bit format is used
uint32_t lo2 = 0;
lo2 = (((hi & 31) << 12) | (lo >> 20)); //get bits 21-37 to check for format len bit
uint8_t idx3 = 1;
while (lo2 > 1) { //find last bit set to 1 (format len bit)
lo2 >>= 1;
idx3++;
}
fmtLen = idx3 + 19;
fc = 0;
cardnum = 0;
if (fmtLen == 26) {
cardnum = (lo >> 1) & 0xFFFF;
fc = (lo >> 17) & 0xFF;
}
if (fmtLen == 32 && (lo & 0x40000000)) { //if 32 bit and Kastle bit set
cardnum = (lo >> 1) & 0xFFFF;
fc = (lo >> 17) & 0xFF;
cc = (lo >> 25) & 0x1F;
}
if (fmtLen == 34) {
cardnum = (lo >> 1) & 0xFFFF;
fc = ((hi & 1) << 15) | (lo >> 17);
}
if (fmtLen == 35) {
cardnum = (lo >> 1) & 0xFFFFF;
fc = ((hi & 1) << 11) | (lo >> 21);
}
if (fmtLen == 36) {
oem = (lo >> 1) & 0x3;
cardnum = (lo >> 3) & 0xFFFF;
fc = (hi & 0x7) << 13 | ((lo >> 19) & 0xFFFF);
}
} else { //if bit 38 is not set then 37 bit format is used
fmtLen = 37;
cardnum = (lo >> 1) & 0x7FFFF;
fc = ((hi & 0xF) << 12) | (lo >> 20);
}
if (fmtLen == 32 && (lo & 0x40000000)) { //if 32 bit and Kastle bit set
PrintAndLogEx(SUCCESS,
"HID Prox (Kastle format) - " _GREEN_("%x%08x (%u)") " - len: " _GREEN_("32") " bit CC: " _GREEN_("%u") " FC: " _GREEN_("%u") " Card: " _GREEN_("%u"), hi, lo, (lo >> 1) & 0xFFFF, cc, fc, cardnum);
} else {
PrintAndLogEx(SUCCESS,
"HID Prox - " _GREEN_("%x%08x (%u)") " - len: " _GREEN_("%u") " bit - OEM: " _GREEN_("%03u") " FC: " _GREEN_("%u")" Card: " _GREEN_("%u"),
hi, lo, cardnum, fmtLen, oem, fc, cardnum);
}
}
wiegand_message_t packed = initialize_message_object(hi2, hi, lo);
HIDTryUnpack(&packed, false);
PrintAndLogEx(DEBUG, "DEBUG: HID idx: %d, Len: %zu, Printing Demod Buffer: ", idx, size);
if (g_debugMode)
@ -206,7 +154,7 @@ static int CmdHIDDemod(const char *Cmd) {
// this read is the "normal" read, which download lf signal and tries to demod here.
static int CmdHIDRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
lf_read(false, 12000);
lf_read(false, 16000);
return demodHID(true);
}
@ -239,62 +187,85 @@ 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 i = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf hid sim",
"Enables simulation of HID card with card number.",
"lf hid sim 2006ec0c86"
"lf hid sim -r 2006ec0c86 -> HID 10301 26 bit\n"
"lf hid sim -r 2e0ec00c87 -> HID Corporate 35 bit\n"
"lf hid sim -r 01f0760643c3 -> HID P10001 40 bit\n"
"lf hid sim -r 01400076000c86 -> HID Corporate 48 bit\n"
"lf hid sim -w H10301 --fc 118 --cn 1603 -> HID 10301 26 bit\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("l", "long", "Simulate HID tag with long ID"),
arg_str1(NULL, NULL, "<hex>", "HID tag ID"),
arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
arg_u64_0(NULL, "cn", "<dec>", "card number"),
arg_int0("i", NULL, "<dec>", "issue level"),
arg_int0("o", "oem", "<dec>", "OEM code"),
arg_strx0("r", "raw", "<hex>", "raw bytes"),
// arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
bool long_id = arg_get_lit(ctx, 1);
char format[16] = {0};
int format_len = 0;
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &format_len);
CLIGetHexWithReturn(ctx, 2, id, &idlen);
wiegand_card_t card;
memset(&card, 0, sizeof(wiegand_card_t));
card.FacilityCode = arg_get_u32_def(ctx, 2, 0);
card.CardNumber = arg_get_u32_def(ctx, 3, 0);
card.IssueLevel = arg_get_u32_def(ctx, 4, 0);
card.OEM = arg_get_u32_def(ctx, 5, 0);
int raw_len = 0;
char raw[40] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)raw, sizeof(raw), &raw_len);
//bool q5 = arg_get_lit(ctx, 7);
CLIParserFree(ctx);
if (long_id) {
for (i=0; i < idlen; ++i) {
hi2 = (hi2 << 4) | (hi >> 28);
hi = (hi << 4) | (lo >> 28);
lo = (lo << 4) | (id[i] >> 4); //get first 4 bits
wiegand_message_t packed;
memset(&packed, 0, sizeof(wiegand_message_t));
hi2 = (hi2 << 4) | (hi >> 28);
hi = (hi << 4) | (lo >> 28);
lo = (lo << 4) | (id[i] & 0xf); //get last 4 bits
// format validation
int format_idx = HIDFindCardFormat((char *)format);
if (format_idx == -1 && raw_len == 0) {
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
return PM3_EINVARG;
}
PrintAndLogEx(INFO, "Simulating HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo);
payload.longFMT = 1;
if (raw_len) {
uint32_t top = 0, mid = 0, bot = 0;
hexstring_to_u96(&top, &mid, &bot, raw);
packed.Top = top;
packed.Mid = mid;
packed.Bot = bot;
} else {
for (i=0; i < idlen; ++i) {
hi = (hi << 4) | (lo >> 28);
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
if (HIDPack(format_idx, &card, &packed) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, "Simulating HID tag with ID: " _GREEN_("%x%08x"), hi, lo);
hi2 = 0;
}
if (raw_len == 0) {
PrintAndLogEx(INFO, "Simulating HID tag");
HIDTryUnpack(&packed, false);
} else {
PrintAndLogEx(INFO, "Simulating HID tag using raw " _GREEN_("%s"), raw);
}
PrintAndLogEx(INFO, "Press pm3-button to abort simulation");
payload.hi2 = hi2;
payload.hi = hi;
payload.lo = lo;
lf_hidsim_t payload;
payload.hi2 = packed.Top;
payload.hi = packed.Mid;
payload.lo = packed.Bot;
payload.longFMT = (packed.Mid > 0xFFF);
clearCommandBuffer();
SendCommandNG(CMD_LF_HID_SIMULATE, (uint8_t *)&payload, sizeof(payload));
@ -303,66 +274,92 @@ static int CmdHIDSim(const char *Cmd) {
PrintAndLogEx(INFO, "Done");
if (resp.status != PM3_EOPABORTED)
return resp.status;
return PM3_SUCCESS;
}
static int CmdHIDClone(const char *Cmd) {
int idlen = 0;
uint8_t id[10] = {0};
uint32_t hi2 = 0, hi = 0, lo = 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"
"lf hid clone -r 2006ec0c86 -> HID 10301 26 bit\n"
"lf hid clone -r 2e0ec00c87 -> HID Corporate 35 bit\n"
"lf hid clone -r 01f0760643c3 -> HID P10001 40 bit\n"
"lf hid clone -r 01400076000c86 -> HID Corporate 48 bit\n"
"lf hid clone -w H10301 --fc 118 --cn 1603 -> HID 10301 26 bit\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("l", "long", "84bit HID long ID"),
arg_str1(NULL, NULL, "<hex>", "HID tag ID"),
arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
arg_u64_0(NULL, "cn", "<dec>", "card number"),
arg_int0("i", NULL, "<dec>", "issue level"),
arg_int0("o", "oem", "<dec>", "OEM code"),
arg_strx0("r", "raw", "<hex>", "raw bytes"),
// arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
bool long_id = arg_get_lit(ctx, 1);
char format[16] = {0};
int format_len = 0;
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &format_len);
CLIGetHexWithReturn(ctx, 2, id, &idlen);
wiegand_card_t card;
memset(&card, 0, sizeof(wiegand_card_t));
card.FacilityCode = arg_get_u32_def(ctx, 2, 0);
card.CardNumber = arg_get_u32_def(ctx, 3, 0);
card.IssueLevel = arg_get_u32_def(ctx, 4, 0);
card.OEM = arg_get_u32_def(ctx, 5, 0);
int raw_len = 0;
char raw[40] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)raw, sizeof(raw), &raw_len);
//bool q5 = arg_get_lit(ctx, 7);
CLIParserFree(ctx);
uint8_t longid[1] = {0};
wiegand_message_t packed;
memset(&packed, 0, sizeof(wiegand_message_t));
if (long_id) {
for (i=0; i < idlen; ++i) {
hi2 = (hi2 << 4) | (hi >> 28);
hi = (hi << 4) | (lo >> 28);
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
// format validation
int format_idx = HIDFindCardFormat((char *)format);
if (format_idx == -1 && raw_len == 0) {
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
return PM3_EINVARG;
}
PrintAndLogEx(INFO, "Preparing to clone HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo);
longid[0] = 1;
if (raw_len) {
uint32_t top = 0, mid = 0, bot = 0;
hexstring_to_u96(&top, &mid, &bot, raw);
packed.Top = top;
packed.Mid = mid;
packed.Bot = bot;
} else {
for (i=0; i < idlen; ++i) {
hi = (hi << 4) | (lo >> 28);
lo = (lo << 4) | (id[i] >> 4); //get first 4 bits
if (HIDPack(format_idx, &card, &packed) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
return PM3_ESOFT;
}
}
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;
if (raw_len == 0) {
PrintAndLogEx(INFO, "Preparing to clone HID tag");
HIDTryUnpack(&packed, false);
} else {
PrintAndLogEx(INFO, "Preparing to clone HID tag using raw " _YELLOW_("%s"), raw);
}
lf_hidsim_t payload;
payload.hi2 = packed.Top;
payload.hi = packed.Mid;
payload.lo = packed.Bot;
payload.longFMT = (packed.Mid > 0xFFF);
clearCommandBuffer();
SendCommandMIX(CMD_LF_HID_CLONE, hi2, hi, lo, longid, sizeof(longid));
SendCommandNG(CMD_LF_HID_CLONE, (uint8_t *)&payload, sizeof(payload));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf hid read`") " to verify");
return PM3_SUCCESS;
@ -399,20 +396,20 @@ static int CmdHIDBrute(const char *Cmd) {
"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"
"lf hid brute -w H10301 --fc 224\n"
"lf hid brute -w H10301 --fc 21 -d 2000\n"
"lf hid brute -v -w H10301 --fc 21 --cn 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_str1("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
arg_int0(NULL, "fn", "<dec>", "facility code"),
arg_int0(NULL, "cn", "<dec>", "card number to start with"),
arg_int0("i", "issue", "<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
@ -426,6 +423,7 @@ static int CmdHIDBrute(const char *Cmd) {
format_idx = HIDFindCardFormat((char *) format);
if (format_idx == -1) {
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
CLIParserFree(ctx);
return PM3_EINVARG;
}
@ -435,6 +433,8 @@ static int CmdHIDBrute(const char *Cmd) {
cn_hi.OEM = arg_get_int_def(ctx, 6, 0);
delay = arg_get_int_def(ctx, 7, 1000);
CLIParserFree(ctx);
if (arg_get_lit(ctx, 8) && arg_get_lit(ctx, 9)) {
direction = 0;
} else if (arg_get_lit(ctx, 8)) {

View file

@ -149,9 +149,14 @@ static int usage_hitag_checkchallenges(void) {
}
static int CmdLFHitagList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("hitag2");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t hitag2");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
/*
uint8_t *got = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));

View file

@ -656,6 +656,7 @@ static int CmdIndalaClone(const char *Cmd) {
if (getIndalaBits(fc, cn, bits) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
free(bits);
return PM3_ESOFT;
}

View file

@ -383,7 +383,7 @@ static int usage_t55xx_clonehelp(void) {
// todo: implement restore
// PrintAndLogEx(NORMAL, _GREEN_("lf em 4x05_write"));
// PrintAndLogEx(NORMAL, _GREEN_("lf em 4x50_write"));
PrintAndLogEx(NORMAL, _GREEN_("lf fdx clone"));
PrintAndLogEx(NORMAL, _GREEN_("lf fdxb clone"));
PrintAndLogEx(NORMAL, _GREEN_("lf gallagher clone"));
PrintAndLogEx(NORMAL, _GREEN_("lf gproxii clone"));
PrintAndLogEx(NORMAL, _GREEN_("lf hid clone"));
@ -598,7 +598,7 @@ bool t55xxAquireAndDetect(bool usepwd, uint32_t password, uint32_t known_block0,
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, m) == false)
continue;
if (tryDetectModulationEx(m, verbose, known_block0, (usepwd) ? password : -1) == false)
if (t55xxTryDetectModulationEx(m, verbose, known_block0, (usepwd) ? password : -1) == false)
continue;
config.downlink_mode = m;
@ -861,7 +861,7 @@ int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, u
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0, downlink_mode) == false)
return PM3_ERFTRANS;
if (tryDetectModulationEx(downlink_mode, false, 0, password) == false) {
if (t55xxTryDetectModulationEx(downlink_mode, false, 0, password) == false) {
PrintAndLogEx(WARNING, "Safety check: Could not detect if PWD bit is set in config block. Exits.");
return PM3_EWRONGANSWER;
} else {
@ -1081,7 +1081,7 @@ static int CmdT55xxDetect(const char *Cmd) {
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, (try_with_pwd && usepwd), password, m) == false)
continue;
if (tryDetectModulationEx(m, T55XX_PrintConfig, 0, (try_with_pwd && usepwd) ? password : -1) == false)
if (t55xxTryDetectModulationEx(m, T55XX_PrintConfig, 0, (try_with_pwd && usepwd) ? password : -1) == false)
continue;
found = true;
@ -1090,7 +1090,7 @@ static int CmdT55xxDetect(const char *Cmd) {
}
} else {
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) {
found = tryDetectModulationEx(downlink_mode, T55XX_PrintConfig, 0, (usepwd) ? password : -1);
found = t55xxTryDetectModulationEx(downlink_mode, T55XX_PrintConfig, 0, (usepwd) ? password : -1);
}
}
@ -1105,7 +1105,7 @@ static int CmdT55xxDetect(const char *Cmd) {
} while (try_with_pwd);
} else {
found = tryDetectModulation(downlink_mode, T55XX_PrintConfig);
found = t55xxTryDetectModulation(downlink_mode, T55XX_PrintConfig);
}
if (found == false) {
@ -1117,11 +1117,11 @@ static int CmdT55xxDetect(const char *Cmd) {
}
// detect configuration?
bool tryDetectModulation(uint8_t downlink_mode, bool print_config) {
return tryDetectModulationEx(downlink_mode, print_config, 0, -1);
bool t55xxTryDetectModulation(uint8_t downlink_mode, bool print_config) {
return t55xxTryDetectModulationEx(downlink_mode, print_config, 0, -1);
}
bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wanted_conf, uint64_t pwd) {
bool t55xxTryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wanted_conf, uint64_t pwd) {
t55xx_conf_block_t tests[15];
int bitRate = 0, clk = 0, firstClockEdge = 0;
@ -3079,7 +3079,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
PrintAndLogEx(SUCCESS, "\nFound a candidate [ " _YELLOW_("%08"PRIX32) " ]", packet->candidate);
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, packet->candidate, downlink_mode)) {
found = tryDetectModulationEx(downlink_mode, T55XX_PrintConfig, 0, packet->candidate);
found = t55xxTryDetectModulationEx(downlink_mode, T55XX_PrintConfig, 0, packet->candidate);
if (found) {
PrintAndLogEx(SUCCESS, "Found valid password [ " _GREEN_("%08"PRIX32) " ]", packet->candidate);
@ -3105,7 +3105,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
continue;
}
found = tryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, cardPassword);
found = t55xxTryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, cardPassword);
if (found) {
PrintAndLogEx(SUCCESS, "Found valid password : [ " _GREEN_("%08"PRIX32) " ]", cardPassword);
dl_mode = 4; // Exit other downlink mode checks
@ -3150,7 +3150,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
continue;
}
found = tryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, curr_password);
found = t55xxTryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, curr_password);
if (found) {
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08"PRIX32) " ]", curr_password);
dl_mode = 4; // Exit other downlink mode checks
@ -3267,7 +3267,7 @@ uint8_t tryOnePassword(uint32_t password, uint8_t downlink_mode) {
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password, dl_mode)) {
// if (getSignalProperties()->isnoise == false) {
// } else {
if (tryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, password)) {
if (t55xxTryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, password)) {
return 1 + (dl_mode << 1);
}
// }

View file

@ -105,8 +105,7 @@ typedef struct {
uint32_t dw;
} t5555_tracedata_t;
typedef struct {
enum {
typedef enum {
DEMOD_NRZ = 0x00,
DEMOD_PSK1 = 0x01,
DEMOD_PSK2 = 0x02,
@ -119,7 +118,10 @@ typedef struct {
DEMOD_ASK = 0x08,
DEMOD_BI = 0x10,
DEMOD_BIa = 0x18,
} modulation;
} t55xx_modulation;
typedef struct {
t55xx_modulation modulation;
bool inverted;
uint8_t offset;
uint32_t block0;
@ -180,9 +182,9 @@ int t55xxWrite(uint8_t block, bool page1, bool usepwd, bool testMode, uint32_t p
bool GetT55xxBlockData(uint32_t *blockdata);
bool DecodeT55xxBlock(void);
bool tryDetectModulation(uint8_t downlink_mode, bool print_config);
//bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wanted_conf);
bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wanted_conf, uint64_t pwd);
bool t55xxTryDetectModulation(uint8_t downlink_mode, bool print_config);
//bool t55xxTryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wanted_conf);
bool t55xxTryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wanted_conf, uint64_t pwd);
bool testKnownConfigBlock(uint32_t block0);
bool tryDetectP1(bool getData);

View file

@ -292,7 +292,7 @@ static int CmdScriptRun(const char *Cmd) {
// get the top of the stack as the error and pop it off
const char *str = lua_tostring(lua_state, lua_gettop(lua_state));
lua_pop(lua_state, 1);
puts(str);
PrintAndLogEx(FAILED, _RED_("error") " - %s", str);
}
//luaL_dofile(lua_state, buf);

View file

@ -844,9 +844,13 @@ static int CmdSmartSetClock(const char *Cmd) {
}
static int CmdSmartList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdTraceList("7816");
return PM3_SUCCESS;
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t 7816");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static void smart_brute_prim(void) {

View file

@ -19,6 +19,7 @@
#include "fileutils.h" // for saveFile
#include "cmdlfhitag.h" // annotate hitag
#include "pm3_cmd.h" // tracelog_hdr_t
#include "cliparser.h" // args..
static int CmdHelp(const char *Cmd);
@ -26,56 +27,6 @@ static int CmdHelp(const char *Cmd);
static uint8_t *g_trace;
static long g_traceLen = 0;
static int usage_trace_list(void) {
PrintAndLogEx(NORMAL, "List protocol data in trace buffer.");
PrintAndLogEx(NORMAL, "Usage: trace list <protocol> [f][c| <0|1>");
PrintAndLogEx(NORMAL, " f - show frame delay times as well");
PrintAndLogEx(NORMAL, " c - mark CRC bytes");
PrintAndLogEx(NORMAL, " r - show relative times (gap and duration)");
PrintAndLogEx(NORMAL, " u - display times in microseconds instead of clock cycles");
PrintAndLogEx(NORMAL, " x - show hexdump to convert to pcap(ng) or to import into Wireshark using encapsulation type \"ISO 14443\"");
PrintAndLogEx(NORMAL, " syntax to use: `text2pcap -t \"%%S.\" -l 264 -n <input-text-file> <output-pcapng-file>`");
PrintAndLogEx(NORMAL, " <0|1> - use data from Tracebuffer, if not set, try to collect a trace from Proxmark3 device.");
PrintAndLogEx(NORMAL, "Supported <protocol> values:");
PrintAndLogEx(NORMAL, " raw - just show raw data without annotations");
PrintAndLogEx(NORMAL, " 14a - interpret data as iso14443a communications");
PrintAndLogEx(NORMAL, " thinfilm - interpret data as Thinfilm communications");
PrintAndLogEx(NORMAL, " topaz - interpret data as Topaz communications");
PrintAndLogEx(NORMAL, " mf - interpret data as iso14443a communications and decrypt crypto1 stream");
PrintAndLogEx(NORMAL, " des - interpret data as DESFire communications");
PrintAndLogEx(NORMAL, " 14b - interpret data as iso14443b communications");
PrintAndLogEx(NORMAL, " 7816 - interpret data as iso7816-4 communications");
PrintAndLogEx(NORMAL, " 15 - interpret data as iso15693 communications");
PrintAndLogEx(NORMAL, " iclass - interpret data as iclass communications");
PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications");
PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications");
PrintAndLogEx(NORMAL, " hitag1 - interpret data as Hitag1 communications");
PrintAndLogEx(NORMAL, " hitag2 - interpret data as Hitag2 communications");
PrintAndLogEx(NORMAL, " hitags - interpret data as HitagS communications");
PrintAndLogEx(NORMAL, " lto - interpret data as LTO-CM communications");
PrintAndLogEx(NORMAL, " cryptorf - interpret data as CryptoRF communitcations");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" trace list 14a f"));
PrintAndLogEx(NORMAL, _YELLOW_(" trace list iclass"));
PrintAndLogEx(NORMAL, _YELLOW_(" trace list 14a 1"));
return PM3_SUCCESS;
}
static int usage_trace_load(void) {
PrintAndLogEx(NORMAL, "Load protocol data from binary file to trace buffer");
PrintAndLogEx(NORMAL, "Usage: trace load <filename>");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" trace load mytracefile.trace"));
return PM3_SUCCESS;
}
static int usage_trace_save(void) {
PrintAndLogEx(NORMAL, "Save protocol data from trace buffer to binary file");
PrintAndLogEx(NORMAL, "Usage: trace save <filename>");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" trace save mytracefile.trace"));
return PM3_SUCCESS;
}
static bool is_last_record(uint16_t tracepos, uint16_t traceLen) {
return ((tracepos + TRACELOG_HDR_LEN) >= traceLen);
}
@ -159,10 +110,8 @@ static uint16_t printHexLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trac
char temp_str2[3] = {0};
sprintf(data_len_str, "%04x", hdr->data_len);
strncat(temp_str1, data_len_str, 2);
temp_str1[2] = '\0';
strncat(temp_str2, data_len_str + 2, 2);
temp_str2[2] = '\0';
memmove(temp_str1, data_len_str, 2);
memmove(temp_str2, data_len_str + 2, 2);
PrintAndLogEx(NORMAL, "0.%010u", hdr->timestamp);
PrintAndLogEx(NORMAL, "000000 00 %s %s %s %s",
@ -203,7 +152,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
data_len = hdr->data_len;
if (tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN(hdr) > traceLen) {
PrintAndLogEx(DEBUG, "trace pos offset %"PRIu32 " larger than reported tracelen %u", tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN(hdr), traceLen);
PrintAndLogEx(DEBUG, "trace pos offset %"PRIu64 " larger than reported tracelen %u", tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN(hdr), traceLen);
return traceLen;
}
@ -212,7 +161,6 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
duration *= 32;
}
uint8_t *frame = hdr->frame;
uint8_t *parityBytes = hdr->frame + data_len;
@ -568,11 +516,24 @@ static int SanityOfflineCheck( bool useTraceBuffer ){
static int CmdTraceLoad(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || (strlen(Cmd) == 1 && cmdp == 'h')) return usage_trace_load();
CLIParserContext *ctx;
CLIParserInit(&ctx, "trace load",
"Load protocol data from binary file to trace buffer\n"
"File extension is (.trace)",
"trace load -f mytracefile"
);
char filename[FILE_PATH_SIZE];
param_getstr(Cmd, 0, filename, sizeof(filename));
void *argtable[] = {
arg_param_begin,
arg_strx0("f", "file", "<filename>", "trace file to load"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
if (g_trace)
free(g_trace);
@ -591,8 +552,24 @@ static int CmdTraceLoad(const char *Cmd) {
static int CmdTraceSave(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || (strlen(Cmd) == 1 && cmdp == 'h')) return usage_trace_save();
CLIParserContext *ctx;
CLIParserInit(&ctx, "trace save",
"Save protocol data from trace buffer to binary file\n"
"File extension is (.trace)",
"trace save -f mytracefile"
);
void *argtable[] = {
arg_param_begin,
arg_strx0("f", "file", "<filename>", "trace file to load"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
if (g_traceLen == 0) {
download_trace();
@ -603,68 +580,68 @@ static int CmdTraceSave(const char *Cmd) {
return PM3_SUCCESS;
}
char filename[FILE_PATH_SIZE];
param_getstr(Cmd, 0, filename, sizeof(filename));
saveFile(filename, ".trace", g_trace, g_traceLen);
return PM3_SUCCESS;
}
int CmdTraceList(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "trace list",
"Annotate trace buffer with selected protocol data\n"
"You can load a trace from file (see `trace load -h`) or it be downloaded from device by default\n",
"trace list -t raw -> just show raw data without annotations\n"
"trace list -t 14a -> interpret as " _YELLOW_("ISO14443-A") " communications\n"
"trace list -t thinfilm -> interpret as " _YELLOW_("Thinfilm") " communications\n"
"trace list -t topaz -> interpret as " _YELLOW_("Topaz") " communications\n"
"trace list -t mf -> interpret as " _YELLOW_("MIFARE Classic") " communications and decrypt crypto1 stream\n"
"trace list -t des -> interpret as " _YELLOW_("MIFARE DESFire") " communications\n"
"trace list -t 14b -> interpret as " _YELLOW_("ISO14443-B") " communications\n"
"trace list -t 7816 -> interpret as " _YELLOW_("ISO7816-4") " communications\n"
"trace list -t 15 -> interpret as " _YELLOW_("ISO15693") " communications\n"
"trace list -t iclass -> interpret as " _YELLOW_("iCLASS") " communications\n"
"trace list -t legic -> interpret as " _YELLOW_("LEGIC") " communications\n"
"trace list -t felica -> interpret as " _YELLOW_("ISO18092 / FeliCa") " communications\n"
"trace list -t hitag1 -> interpret as " _YELLOW_("Hitag1") " communications\n"
"trace list -t hitag2 -> interpret as " _YELLOW_("Hitag2") " communications\n"
"trace list -t hitags -> interpret as " _YELLOW_("HitagS") " communications\n"
"trace list -t lto -> interpret as " _YELLOW_("LTO-CM") " communications\n"
"trace list -t cryptorf -> interpret as " _YELLOW_("CryptoRF") " communitcations\n"
"trace list -t 14a f -> show frame delay times\n"
"trace list -t 14a 1 -> use trace buffer "
);
void *argtable[] = {
arg_param_begin,
arg_lit0("1", "buffer", "use data from trace buffer"),
arg_lit0("f", NULL, "show frame delay times"),
arg_lit0("c", NULL, "mark CRC bytes"),
arg_lit0("r", NULL, "show relative times (gap and duration)"),
arg_lit0("u", NULL, "display times in microseconds instead of clock cycles"),
arg_lit0("x", NULL, "show hexdump to convert to pcap(ng)\n"
" or to import into Wireshark using encapsulation type \"ISO 14443\""),
arg_strx0("t", "type", NULL, "protocol to annotate the trace"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
bool use_buffer = arg_get_lit(ctx, 1);
bool show_wait_cycles = arg_get_lit(ctx, 2);
bool mark_crc = arg_get_lit(ctx, 3);
bool use_relative = arg_get_lit(ctx, 4);
bool use_us = arg_get_lit(ctx, 5);
bool show_hex = arg_get_lit(ctx, 6);
int tlen = 0;
char type[10] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)type, sizeof(type), &tlen);
str_lower(type);
CLIParserFree(ctx);
clearCommandBuffer();
bool showWaitCycles = false, markCRCBytes = false;
bool showHex = false, isOnline = true;
bool use_us = false, use_relative = false;
bool errors = false;
uint8_t protocol = 0;
char type[10] = {0};
char cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
int slen = param_getstr(Cmd, cmdp, type, sizeof(type));
if (slen == 1) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_trace_list();
case 'f':
showWaitCycles = true;
cmdp++;
break;
case 'c':
markCRCBytes = true;
cmdp++;
break;
case 'x':
showHex = true;
cmdp++;
break;
case '0':
isOnline = true;
cmdp++;
break;
case '1':
isOnline = false;
cmdp++;
break;
case 'r':
use_relative = true;
cmdp++;
break;
case 'u':
use_us = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
} else {
str_lower(type);
// no crc, no annotations
uint8_t protocol = -1;
// validate type of output
if (strcmp(type, "iclass") == 0) protocol = ICLASS;
@ -683,19 +660,9 @@ int CmdTraceList(const char *Cmd) {
else if (strcmp(type, "thinfilm") == 0) protocol = THINFILM;
else if (strcmp(type, "lto") == 0) protocol = LTO;
else if (strcmp(type, "cryptorf") == 0) protocol = PROTO_CRYPTORF;
else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations
else errors = true;
else if (strcmp(type, "raw") == 0) protocol = -1;
cmdp++;
}
}
//if (!SanityOfflineCheck(isOnline)) return 1;
//Validations
if (errors) return usage_trace_list();
if (isOnline) {
if (use_buffer == false || (g_traceLen == 0)) {
download_trace();
}
@ -711,7 +678,7 @@ int CmdTraceList(const char *Cmd) {
printFelica(g_traceLen, g_trace);
} */
if (showHex) {
if (show_hex) {
while (tracepos < g_traceLen) {
tracepos = printHexLine(tracepos, g_traceLen, g_trace, protocol);
}
@ -788,12 +755,16 @@ int CmdTraceList(const char *Cmd) {
}
while (tracepos < g_traceLen) {
tracepos = printTraceLine(tracepos, g_traceLen, g_trace, protocol, showWaitCycles, markCRCBytes, prev_EOT, use_us);
tracepos = printTraceLine(tracepos, g_traceLen, g_trace, protocol, show_wait_cycles, mark_crc, prev_EOT, use_us);
if (kbd_enter_pressed())
break;
}
}
if (show_hex)
PrintAndLogEx(HINT, "syntax to use: " _YELLOW_("`text2pcap -t \"%%S.\" -l 264 -n <input-text-file> <output-pcapng-file>`"));
return PM3_SUCCESS;
}

View file

@ -76,7 +76,7 @@ int CmdWiegandEncode(const char *Cmd) {
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_str1("w", "wiegand", "<format>", "see `wiegand list` for available formats"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);

View file

@ -1772,8 +1772,13 @@ static int CmdEMVScan(const char *Cmd) {
}
static int CmdEMVList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
return CmdTraceList("7816");
char args[128] = {0};
if (strlen(Cmd) == 0) {
snprintf(args, sizeof(args), "-t 7816");
} else {
strncpy(args, Cmd, sizeof(args) - 1);
}
return CmdTraceList(args);
}
static int CmdEMVTest(const char *Cmd) {

View file

@ -119,15 +119,17 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose) {
MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)));
if (bitand_is_zero(&g_one, &prints[i])) {
if (verbose)
PrintAndLogEx(FAILED, "No fingerprint found.\n");
goto cleanup;
}
mbedtls_mpi_free(&g_one);
mbedtls_mpi_free(&t_temp);
mbedtls_mpi_free(&t_prime);
if (bitand_is_zero(&g_one, &prints[i])) {
if (verbose) {
PrintAndLogEx(FAILED, "No fingerprint found.\n");
}
mbedtls_mpi_free(&g_one);
goto cleanup;
}
mbedtls_mpi_free(&g_one);
}
ret = true;

View file

@ -9,9 +9,7 @@
//-----------------------------------------------------------------------------
#include "emvjson.h"
#include <string.h>
#include "commonutil.h" // ARRAYLEN
#include "ui.h"
#include "util.h"
@ -75,7 +73,7 @@ int JsonSaveJsonObject(json_t *root, const char *path, json_t *value) {
return 1;
if (path[0] == '$') {
if (json_path_set(root, path, value, 0, &error)) {
if (json_path_set_new(root, path, value, 0, &error)) {
PrintAndLogEx(ERR, "ERROR: can't set json path: %s", error.text);
return 2;
} else {

View file

@ -573,16 +573,16 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
int res = json_dump_file(root, fileName, JSON_INDENT(2));
if (res) {
PrintAndLogEx(FAILED, "error: can't save the file: " _YELLOW_("%s"), fileName);
json_decref(root);
retval = 200;
goto out;
}
if (verbose)
PrintAndLogEx(SUCCESS, "saved to json file " _YELLOW_("%s"), fileName);
json_decref(root);
if (verbose) {
PrintAndLogEx(SUCCESS, "saved to json file " _YELLOW_("%s"), fileName);
}
out:
json_decref(root);
free(fileName);
return retval;
}

View file

@ -190,12 +190,10 @@ int GetAskClock(const char *str, bool printAns) {
return clock1;
}
uint8_t GetPskCarrier(const char *str, bool printAns) {
int GetPskCarrier(bool verbose) {
if (getSignalProperties()->isnoise)
return -1;
uint8_t carrier = 0;
uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
if (bits == NULL) {
PrintAndLogEx(WARNING, "Failed to allocate memory");
@ -211,16 +209,18 @@ uint8_t GetPskCarrier(const char *str, bool printAns) {
uint16_t fc = countFC(bits, size, false);
free(bits);
carrier = fc & 0xFF;
uint8_t carrier = fc & 0xFF;
if (carrier != 2 && carrier != 4 && carrier != 8) return 0;
if ((fc >> 8) == 10 && carrier == 8) return 0;
// Only print this message if we're not looping something
if (printAns)
if (verbose)
PrintAndLogEx(SUCCESS, "Auto-detected PSK carrier rate: %d", carrier);
return carrier;
}
int GetPskClock(const char *str, bool printAns) {
int GetPskClock(const char *str, bool verbose) {
if (getSignalProperties()->isnoise)
return -1;
@ -251,14 +251,14 @@ int GetPskClock(const char *str, bool printAns) {
setClockGrid(clock1, firstPhaseShiftLoc);
// Only print this message if we're not looping something
if (printAns)
if (verbose)
PrintAndLogEx(SUCCESS, "Auto-detected clock rate: %d", clock1);
free(bits);
return clock1;
}
int GetNrzClock(const char *str, bool printAns) {
int GetNrzClock(const char *str, bool verbose) {
if (getSignalProperties()->isnoise)
return -1;
@ -285,7 +285,7 @@ int GetNrzClock(const char *str, bool printAns) {
clock1 = DetectNRZClock(bits, size, 0, &clkStartIdx);
setClockGrid(clock1, clkStartIdx);
// Only print this message if we're not looping something
if (printAns)
if (verbose)
PrintAndLogEx(SUCCESS, "Auto-detected clock rate: %d", clock1);
free(bits);
@ -294,7 +294,7 @@ int GetNrzClock(const char *str, bool printAns) {
//by marshmellow
//attempt to detect the field clock and bit clock for FSK
int GetFskClock(const char *str, bool printAns) {
int GetFskClock(const char *str, bool verbose) {
int clock1 = param_get32ex(str, 0, 0, 10);
if (clock1 != 0)
@ -307,7 +307,7 @@ int GetFskClock(const char *str, bool printAns) {
return 0;
if ((fc1 == 10 && fc2 == 8) || (fc1 == 8 && fc2 == 5)) {
if (printAns)
if (verbose)
PrintAndLogEx(SUCCESS, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1);
setClockGrid(rf1, firstClockEdge);

View file

@ -27,11 +27,11 @@ void convertGraphFromBitstream(void);
void convertGraphFromBitstreamEx(int hi, int low);
bool isGraphBitstream(void);
int GetAskClock(const char *str, bool printAns);
int GetPskClock(const char *str, bool printAns);
uint8_t GetPskCarrier(const char *str, bool printAns);
int GetNrzClock(const char *str, bool printAns);
int GetFskClock(const char *str, bool printAns);
int GetAskClock(const char *str, bool verbose);
int GetPskClock(const char *str, bool verbose);
int GetPskCarrier(bool verbose);
int GetNrzClock(const char *str, bool verbose);
int GetFskClock(const char *str, bool verbose);
bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge);
#define MAX_GRAPH_TRACE_LEN (40000 * 8)

View file

@ -38,9 +38,7 @@ static void jsonp_free(void *ptr) {
}
static char *jsonp_strndup(const char *str, size_t len) {
char *new_str;
new_str = jsonp_malloc(len + 1);
char *new_str = jsonp_malloc(len + 1);
if (!new_str)
return NULL;

View file

@ -816,14 +816,16 @@ int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidt
return PM3_ESOFT;
}
struct p *payload = calloc(1, sizeof(struct p) + size);
size_t paylen = sizeof(struct p) + size;
struct p *payload = calloc(1, paylen);
payload->blockno = blockNum;
payload->blockcnt = blocksCount;
payload->blockwidth = blockBtWidth;
memcpy(payload->data, data, size);
clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_EML_MEMSET, (uint8_t *)payload, sizeof(payload) + size);
SendCommandNG(CMD_HF_MIFARE_EML_MEMSET, (uint8_t *)payload, paylen);
free(payload);
return PM3_SUCCESS;
}
@ -1178,7 +1180,7 @@ int detect_mf_magic(bool is_mfc) {
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 2 / CUID"));
break;
case MAGIC_GEN_3:
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 3 / APDU"));
PrintAndLogEx(SUCCESS, "Magic capabilities : possibly " _GREEN_("Gen 3 / APDU"));
break;
case MAGIC_GEN_UNFUSED:
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Write Once / FUID"));

View file

@ -12,7 +12,7 @@
// Add the new setting to the session_arg_t; in ui.h
// Add the default value for the setting in the settings_load page below
// Update the preferences_load_callback to load your setting into the stucture
// Update the preferences_save_callback to enusre your setting gets saved when needed.
// Update the preferences_save_callback to ensure your setting gets saved when needed.
// use the preference as needed : session.<preference name>
// Can use (session.preferences_loaded) to check if json settings file was used
//-----------------------------------------------------------------------------
@ -52,6 +52,7 @@ int preferences_load(void) {
session.overlay.y = 60 + session.plot.y + session.plot.h;
session.overlay.h = 200;
session.overlay.w = session.plot.w;
session.overlay_sliders = true;
session.show_hints = false;
// setDefaultPath (spDefault, "");
@ -78,6 +79,11 @@ int preferences_load(void) {
setDefaultPath (spTrace, ".");
*/
if (session.incognito) {
PrintAndLogEx(INFO, "No preferences file will be loaded");
return PM3_SUCCESS;
}
// loadFileJson wants these, so pass in place holder values, though not used
// in settings load;
uint8_t dummyData = 0x00;
@ -100,7 +106,10 @@ int preferences_load(void) {
// Save all settings from memory (struct) to file
int preferences_save(void) {
// Note sure if backup has value ?
if (session.incognito) {
PrintAndLogEx(INFO, "No preferences file will be saved");
return PM3_SUCCESS;
}
PrintAndLogEx(INFO, "Saving preferences...");
char *fn = prefGetFilename();
@ -185,6 +194,7 @@ void preferences_save_callback(json_t *root) {
JsonSaveInt(root, "window.overlay.ypos", session.overlay.y);
JsonSaveInt(root, "window.overlay.hsize", session.overlay.h);
JsonSaveInt(root, "window.overlay.wsize", session.overlay.w);
JsonSaveBoolean(root, "window.overlay.sliders", session.overlay_sliders);
// Log level, convert to text
switch (session.client_debug_level) {
@ -225,7 +235,7 @@ void preferences_save_callback(json_t *root) {
void preferences_load_callback(json_t *root) {
json_error_t up_error = {0};
bool b1;
int b1;
int i1;
const char *s1;
char tempStr [500]; // to use str_lower() since json unpack uses const char *
@ -270,6 +280,8 @@ void preferences_load_callback(json_t *root) {
session.overlay.h = i1;
if (json_unpack_ex(root, &up_error, 0, "{s:i}", "window.overlay.wsize", &i1) == 0)
session.overlay.w = i1;
if (json_unpack_ex(root, &up_error, 0, "{s:b}", "window.overlay.sliders", &b1) == 0)
session.overlay_sliders = (bool)b1;
// show options
if (json_unpack_ex(root, &up_error, 0, "{s:s}", "show.emoji", &s1) == 0) {
@ -282,10 +294,10 @@ void preferences_load_callback(json_t *root) {
}
if (json_unpack_ex(root, &up_error, 0, "{s:b}", "show.hints", &b1) == 0)
session.show_hints = b1;
session.show_hints = (bool)b1;
if (json_unpack_ex(root, &up_error, 0, "{s:b}", "os.supports.colors", &b1) == 0)
session.supports_colors = b1;
session.supports_colors = (bool)b1;
/*
// Logging Level
if (json_unpack_ex(root, &up_error, 0, "{s:s}", "device.debug.level", &s1) == 0) {
@ -353,6 +365,16 @@ static int usage_set_hints(void) {
PrintAndLogEx(NORMAL, " "_GREEN_("on")" - Display hints");
return PM3_SUCCESS;
}
static int usage_set_plotsliders(void) {
PrintAndLogEx(NORMAL, "Usage: pref set plotsliders <on | off>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " "_GREEN_("help")" - This help");
PrintAndLogEx(NORMAL, " "_GREEN_("on")" - show plot slider controls");
PrintAndLogEx(NORMAL, " "_GREEN_("off")" - hide plot slider controls");
return PM3_SUCCESS;
}
/*
static int usage_set_savePaths(void) {
PrintAndLogEx(NORMAL, "Usage: pref set savepaths [help] [create] [default <path>] [dump <path>] [trace <path>]");
@ -492,6 +514,13 @@ static void showHintsState(prefShowOpt_t opt) {
PrintAndLogEx(INFO, " %s hints.................. "_WHITE_("off"), prefShowMsg(opt));
}
static void showPlotSliderState(prefShowOpt_t opt) {
if (session.overlay_sliders)
PrintAndLogEx(INFO, " %s show plot sliders...... "_GREEN_("on"), prefShowMsg(opt));
else
PrintAndLogEx(INFO, " %s show plot sliders...... "_WHITE_("off"), prefShowMsg(opt));
}
static int setCmdEmoji(const char *Cmd) {
uint8_t cmdp = 0;
@ -755,6 +784,52 @@ static int setCmdHint(const char *Cmd) {
return PM3_SUCCESS;
}
static int setCmdPlotSliders(const char *Cmd) {
uint8_t cmdp = 0;
bool errors = false;
bool validValue = false;
char strOpt[50];
bool newValue = session.overlay_sliders;
if (param_getchar(Cmd, cmdp) == 0x00)
return usage_set_plotsliders();
while ((param_getchar(Cmd, cmdp) != 0x00) && !errors) {
if (param_getstr(Cmd, cmdp++, strOpt, sizeof(strOpt)) != 0) {
str_lower(strOpt); // convert to lowercase
if (strncmp(strOpt, "help", 4) == 0)
return usage_set_plotsliders();
if (strncmp(strOpt, "off", 3) == 0) {
validValue = true;
newValue = false;
}
if (strncmp(strOpt, "on", 2) == 0) {
validValue = true;
newValue = true;
}
if (validValue) {
if (session.overlay_sliders != newValue) {// changed
showPlotSliderState(prefShowOLD);
session.overlay_sliders = newValue;
showPlotSliderState(prefShowNEW);
preferences_save();
} else {
PrintAndLogEx(INFO, "nothing changed");
showPlotSliderState(prefShowNone);
}
} else {
PrintAndLogEx(ERR, "invalid option");
return usage_set_plotsliders();
}
}
}
return PM3_SUCCESS;
}
/*
static int setCmdSavePaths (const char *Cmd) {
uint8_t cmdp = 0;
@ -866,6 +941,11 @@ static int getCmdDebug(const char *Cmd) {
return PM3_SUCCESS;
}
static int getCmdPlotSlider(const char *Cmd) {
showPlotSliderState(prefShowNone);
return PM3_SUCCESS;
}
static command_t getCommandTable[] = {
// {"help", getCmdHelp, AlwaysAvailable, "This help"},
{"emoji", getCmdEmoji, AlwaysAvailable, "Get emoji display preference"},
@ -873,6 +953,7 @@ static command_t getCommandTable[] = {
{"color", getCmdColor, AlwaysAvailable, "Get color support preference"},
// {"defaultsavepaths", getCmdSavePaths, AlwaysAvailable, "... to be adjusted next ... "},
{"clientdebug", getCmdDebug, AlwaysAvailable, "Get client debug level preference"},
{"plotsliders", getCmdPlotSlider, AlwaysAvailable, "Get plot slider display preference"},
// {"devicedebug", getCmdDeviceDebug, AlwaysAvailable, "Get device debug level"},
{NULL, NULL, NULL, NULL}
};
@ -884,6 +965,7 @@ static command_t setCommandTable[] = {
{"color", setCmdColor, AlwaysAvailable, "Set color support"},
// {"defaultsavepaths", setCmdSavePaths, AlwaysAvailable, "... to be adjusted next ... "},
{"clientdebug", setCmdDebug, AlwaysAvailable, "Set client debug level"},
{"plotsliders", setCmdPlotSliders, AlwaysAvailable, "Set plot slider display"},
// {"devicedebug", setCmdDeviceDebug, AlwaysAvailable, "Set device debug level"},
{NULL, NULL, NULL, NULL}
};
@ -912,8 +994,7 @@ static int CmdPrefShow(const char *Cmd) {
PrintAndLogEx(INFO, "Using "_YELLOW_("%s"), fn);
free(fn);
} else {
PrintAndLogEx(ERR, "Preferences not loaded");
return PM3_ESOFT;
PrintAndLogEx(WARNING, "Preferences file not loaded");
}
PrintAndLogEx(INFO, "Current settings");
@ -925,8 +1006,8 @@ static int CmdPrefShow(const char *Cmd) {
// showSavePathState(spDefault, prefShowNone);
// showSavePathState(spDump, prefShowNone);
// showSavePathState(spTrace, prefShowNone);
showClientDebugState(prefShowNone);
showPlotSliderState(prefShowNone);
// showDeviceDebugState(prefShowNone);
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;

View file

@ -28,7 +28,7 @@ void ExitGraphics(void);
extern double CursorScaleFactor;
extern char CursorScaleFactorUnit[11];
extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, GridOffset;
extern double PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, GridOffset;
extern uint32_t CursorCPos, CursorDPos;
extern int CommandFinished;
extern int offline;

View file

@ -7,6 +7,7 @@
//-----------------------------------------------------------------------------
// GUI (QT)
//-----------------------------------------------------------------------------
#define __STDC_FORMAT_MACROS
#include "proxguiqt.h"
#include <inttypes.h>
#include <stdbool.h>
@ -251,7 +252,8 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) {
QString ct = QString("[*]Slider [ %1 ]").arg(conn.serial_port_name);
controlWidget->setWindowTitle(ct);
controlWidget->show();
// The hide/show event functions should take care of this.
// controlWidget->show();
// now that is up, reset pos/size change flags
session.window_changed = false;
@ -289,7 +291,10 @@ void ProxWidget::hideEvent(QHideEvent *event) {
plot->hide();
}
void ProxWidget::showEvent(QShowEvent *event) {
if (session.overlay_sliders)
controlWidget->show();
else
controlWidget->hide();
plot->show();
}
void ProxWidget::moveEvent(QMoveEvent *event) {
@ -498,17 +503,17 @@ void Plot::plotGridLines(QPainter *painter, QRect r) {
// set GridOffset
if (PlotGridX <= 0) return;
int offset = GridOffset;
double offset = GridOffset;
if (GridLocked && PlotGridX) {
offset = GridOffset + PlotGridX - (GraphStart % PlotGridX);
offset = GridOffset + PlotGridX - fmod(GraphStart, PlotGridX);
} else if (!GridLocked && GraphStart > 0 && PlotGridX) {
offset = PlotGridX - ((GraphStart - offset) % PlotGridX) + GraphStart - unlockStart;
offset = PlotGridX - fmod(GraphStart - offset, PlotGridX) + GraphStart - unlockStart;
}
offset %= PlotGridX;
offset = fmod(offset, PlotGridX);
if (offset < 0) offset += PlotGridX;
int i;
int grid_delta_x = (int)(PlotGridX * GraphPixelsPerPoint);
double i;
double grid_delta_x = PlotGridX * GraphPixelsPerPoint;
int grid_delta_y = PlotGridY;
if ((PlotGridX > 0) && ((PlotGridX * GraphPixelsPerPoint) > 1)) {
@ -591,7 +596,7 @@ void Plot::paintEvent(QPaintEvent *event) {
painter.drawLine(xCoordOf(CursorCPos, plotRect), plotRect.top(), xCoordOf(CursorCPos, plotRect), plotRect.bottom());
}
if (CursorDPos > GraphStart && xCoordOf(CursorDPos, plotRect) < plotRect.right()) {
painter.setPen(QColor(0, 0, 205)); //light blue
painter.setPen(QColor(100, 209, 246)); //light blue
painter.drawLine(xCoordOf(CursorDPos, plotRect), plotRect.top(), xCoordOf(CursorDPos, plotRect), plotRect.bottom());
}
@ -605,7 +610,7 @@ void Plot::paintEvent(QPaintEvent *event) {
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",
sprintf(str, "@%u..%u dt=%i %szoom=%2.2f CursorAPos=%u CursorBPos=%u GridX=%lf GridY=%lf (%s) GridXoffset=%lf",
GraphStart,
GraphStop,
CursorBPos - CursorAPos,
@ -633,11 +638,12 @@ Plot::Plot(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoin
palette.setColor(QPalette::Button, QColor(100, 100, 100));
setPalette(palette);
setAutoFillBackground(true);
CursorAPos = 0;
CursorBPos = 0;
GraphStop = 0;
setWindowTitle(tr("Sliders"));
master = parent;
}
@ -647,15 +653,18 @@ void Plot::closeEvent(QCloseEvent *event) {
g_useOverlays = false;
}
void Plot::Zoom(double factor, int refX) {
void Plot::Zoom(double factor, uint32_t refX) {
if (factor >= 1) { // Zoom in
if (GraphPixelsPerPoint <= 25 * factor) {
GraphPixelsPerPoint *= factor;
if (refX > GraphStart) {
GraphStart += (refX - GraphStart) - ((refX - GraphStart) / factor);
}
}
} else { // Zoom out
if (GraphPixelsPerPoint >= 0.01 / factor) {
GraphPixelsPerPoint *= factor;
if (refX > GraphStart) {
if (GraphStart >= ((refX - GraphStart) / factor) - (refX - GraphStart)) {
GraphStart -= ((refX - GraphStart) / factor) - (refX - GraphStart);
} else {
@ -664,6 +673,7 @@ void Plot::Zoom(double factor, int refX) {
}
}
}
}
void Plot::Move(int offset) {
if (offset > 0) { // Move right
@ -693,6 +703,16 @@ void Plot::Trim(void) {
if ((CursorAPos == 0) || (CursorBPos == 0)) { // if we don't have both cursors set
lref = GraphStart;
rref = GraphStop;
if (CursorAPos >= lref) {
CursorAPos -= lref;
} else {
CursorAPos = 0;
}
if (CursorBPos >= lref) {
CursorBPos -= lref;
} else {
CursorBPos = 0;
}
} else {
lref = CursorAPos < CursorBPos ? CursorAPos : CursorBPos;
rref = CursorAPos < CursorBPos ? CursorBPos : CursorAPos;
@ -705,6 +725,7 @@ void Plot::Trim(void) {
CursorAPos -= lref;
CursorBPos -= lref;
}
g_DemodStartIdx -= lref;
for (uint32_t i = lref; i < rref; ++i)
GraphBuffer[i - lref] = GraphBuffer[i];
GraphTraceLen = rref - lref;
@ -722,9 +743,9 @@ void Plot::wheelEvent(QWheelEvent *event) {
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
int x = event->position().x();
uint32_t x = event->position().x();
#else
int x = event->x();
uint32_t x = event->x();
#endif
x -= WIDTH_AXES;
x = (int)(x / GraphPixelsPerPoint);
@ -765,10 +786,11 @@ void Plot::mouseMoveEvent(QMouseEvent *event) {
void Plot::keyPressEvent(QKeyEvent *event) {
uint32_t offset; // Left/right movement offset (in sample size)
const double zoom_offset = 1.148698354997035; // 2**(1/5)
if (event->modifiers() & Qt::ShiftModifier) {
if (PlotGridX)
offset = PageWidth - (PageWidth % PlotGridX);
offset = PageWidth - fmod(PageWidth, PlotGridX);
else
offset = PageWidth;
} else {
@ -781,18 +803,34 @@ void Plot::keyPressEvent(QKeyEvent *event) {
switch (event->key()) {
case Qt::Key_Down:
if (event->modifiers() & Qt::ShiftModifier) {
if (event->modifiers() & Qt::ControlModifier) {
Zoom(zoom_offset, CursorBPos);
} else {
Zoom(2, CursorBPos);
}
} else {
if (event->modifiers() & Qt::ControlModifier) {
Zoom(zoom_offset, CursorAPos);
} else {
Zoom(2, CursorAPos);
}
}
break;
case Qt::Key_Up:
if (event->modifiers() & Qt::ShiftModifier) {
if (event->modifiers() & Qt::ControlModifier) {
Zoom(1.0 / zoom_offset, CursorBPos);
} else {
Zoom(0.5, CursorBPos);
}
} else {
if (event->modifiers() & Qt::ControlModifier) {
Zoom(1.0 / zoom_offset, CursorAPos);
} else {
Zoom(0.5, CursorAPos);
}
}
break;
case Qt::Key_Right:
@ -803,6 +841,14 @@ void Plot::keyPressEvent(QKeyEvent *event) {
Move(-offset);
break;
case Qt::Key_Greater:
g_DemodStartIdx += 1;
break;
case Qt::Key_Less:
g_DemodStartIdx -= 1;
break;
case Qt::Key_G:
if (PlotGridX || PlotGridY) {
PlotGridX = 0;
@ -819,36 +865,33 @@ void Plot::keyPressEvent(QKeyEvent *event) {
break;
case Qt::Key_H:
puts("\n-----------------------------------------------------------------------");
puts("PLOT window keystrokes");
puts("\tKey Action");
puts("-----------------------------------------------------------------------");
puts("\tUP Zoom out around yellow cursor");
puts("\t<SHIFT> UP Zoom out around purple cursor");
puts("\t<SHIFT> WHEEL MOUSE UP Zoom out around mouse cursor");
puts("\tDOWN Zoom in around yellow cursor");
puts("\t<SHIFT> DOWN Zoom in around purple cursor");
puts("\t<SHIFT> WHEEL MOUSE DOWN Zoom in around mouse cursor");
puts("\tG Toggle grid display");
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");
puts("\tPGDOWN Page right");
puts("\tLEFT Move left");
puts("\tRIGHT Move right");
puts("\tWHEEL MOUSE UP Move left");
puts("\tWHEEL MOUSE DOWN Move right");
puts("\t<CTLR> LEFT Move left 1 sample");
puts("\t<CTLR> RIGHT Move right 1 sample");
puts("\t<SHIFT> LEFT Page left");
puts("\t<SHIFT> RIGHT Page right");
puts("\tLEFT MOUSE CLICK Set yellow cursor");
puts("\tRIGHT MOUSE CLICK Set purple cursor");
puts("-----------------------------------------------------------------------");
g_printAndLog = PRINTANDLOG_PRINT;
PrintAndLogEx(NORMAL, "\n\n" _CYAN_("PLOT window keystrokes and mouse events"));
PrintAndLogEx(NORMAL, "\n" _GREEN_("Move:"));
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9 + 9, _RED_("Home") "/" _RED_("End"), "Move to the start/end of the graph");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, _YELLOW_("Mouse wheel"), "Move left/right");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9 + 9, _RED_("Left") "/" _RED_("Right"), "Move left/right");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, " + " _RED_("Ctrl"), "... by 1 sample");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, " + " _RED_("Shift"), "... by 1 window");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9 + 9, _RED_("PgUp") "/" _RED_("PgDown"), "Move left/right by 1 window");
PrintAndLogEx(NORMAL, "\n" _GREEN_("Zoom:"));
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9 + 9, _RED_("Shift") " + " _YELLOW_("Mouse wheel"), "Zoom in/out around mouse cursor");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9 + 9, _RED_("Down") "/" _RED_("Up"), "Zoom in/out around yellow cursor");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, " + " _RED_("Ctrl"), "... with smaller increment");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, " + " _RED_("Shift"), "... around purple cursor");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, _RED_("h"), "Show this help");
PrintAndLogEx(NORMAL, "\n" _GREEN_("Trim:"));
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, _RED_("t"), "Trim data on window or on cursors if defined");
PrintAndLogEx(NORMAL, "\n" _GREEN_("Grid and demod:"));
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, _RED_("g"), "Toggle grid and demodulation plot display");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, _RED_("l"), "Toggle lock grid relative to samples");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9 + 9, _RED_("<") "/" _RED_(">"), "Move demodulation left/right relative to samples");
PrintAndLogEx(NORMAL, "\n" _GREEN_("Misc:"));
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, _YELLOW_("Left mouse click"), "Set yellow cursor");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, _YELLOW_("Right mouse click"), "Set purple cursor");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, _RED_("h"), "Show this help");
PrintAndLogEx(NORMAL, " %-*s%s", 25 + 9, _RED_("q"), "Close plot window");
g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG;
break;
case Qt::Key_L:

View file

@ -51,7 +51,7 @@ class Plot: public QWidget {
protected:
void paintEvent(QPaintEvent *event);
void closeEvent(QCloseEvent *event);
void Zoom(double factor, int refX);
void Zoom(double factor, uint32_t refX);
void Move(int offset);
void Trim(void);
void wheelEvent(QWheelEvent *event);

View file

@ -245,6 +245,9 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
#ifdef HAVE_READLINE
session.history_path = NULL;
if (session.incognito) {
PrintAndLogEx(INFO, "No history will be recorded");
} else {
if (searchHomeFilePath(&session.history_path, NULL, PROXHISTORY, true) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "No history will be recorded");
session.history_path = NULL;
@ -262,6 +265,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
rl_set_signals();
read_history(session.history_path);
}
}
#endif
// loops every time enter is pressed...
@ -565,6 +569,7 @@ static void show_help(bool showFullHelp, char *exec_name) {
PrintAndLogEx(NORMAL, " -l/--lua <lua script file> execute lua script.");
PrintAndLogEx(NORMAL, " -s/--script-file <cmd_script_file> script file with one Proxmark3 command per line");
PrintAndLogEx(NORMAL, " -i/--interactive enter interactive mode after executing the script or the command");
PrintAndLogEx(NORMAL, " --incognito do not use history, prefs file nor log files");
PrintAndLogEx(NORMAL, "\nOptions in flasher mode:");
PrintAndLogEx(NORMAL, " --flash flash Proxmark3, requires at least one --image");
PrintAndLogEx(NORMAL, " --unlock-bootloader Enable flashing of bootloader area *DANGEROUS* (need --flash or --flash-info)");
@ -698,6 +703,7 @@ int main(int argc, char *argv[]) {
session.pm3_present = false;
session.help_dump_mode = false;
session.incognito = false;
bool waitCOMPort = false;
bool addLuaExec = false;
bool stayInCommandLoop = false;
@ -903,6 +909,12 @@ int main(int argc, char *argv[]) {
continue;
}
// do not use history nor log files
if (strcmp(argv[i], "--incognito") == 0) {
session.incognito = true;
continue;
}
// go to flash mode
if (strcmp(argv[i], "--flash") == 0) {
flash_mode = true;
@ -1008,7 +1020,7 @@ int main(int argc, char *argv[]) {
// Save settings if not loaded from settings json file.
// Doing this here will ensure other checks and updates are saved to over rule default
// e.g. Linux color use check
if (!session.preferences_loaded) {
if ((!session.preferences_loaded) && (!session.incognito)) {
PrintAndLogEx(INFO, "Creating initial preferences file"); // json save reports file name, so just info msg here
preferences_save(); // Save defaults
session.preferences_loaded = true;

View file

@ -36,6 +36,7 @@
#include "fileutils.h" // searchfile
#include "cmdlf.h" // lf_config
#include "generator.h"
#include "cmdlfem4x.h" // read 4305
static int returnToLuaWithError(lua_State *L, const char *fmt, ...) {
char buffer[200];
@ -1001,7 +1002,7 @@ static int l_T55xx_readblock(lua_State *L) {
return returnToLuaWithError(L, "Failed to read config block");
}
if (!tryDetectModulation(0, true)) { // Default to prev. behaviour (default dl mode and print config)
if (!t55xxTryDetectModulation(0, true)) { // Default to prev. behaviour (default dl mode and print config)
PrintAndLogEx(NORMAL, "Safety Check: Could not detect if PWD bit is set in config block. Exits.");
return 0;
} else {
@ -1077,7 +1078,7 @@ static int l_T55xx_detect(lua_State *L) {
}
}
isok = tryDetectModulation(0, true); // Default to prev. behaviour (default dl mode and print config)
isok = t55xxTryDetectModulation(0, true); // Default to prev. behaviour (default dl mode and print config)
if (isok == false) {
return returnToLuaWithError(L, "Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'");
}
@ -1087,6 +1088,46 @@ static int l_T55xx_detect(lua_State *L) {
return 2;
}
//
static int l_em4x05_read(lua_State *L) {
bool use_pwd = false;
uint32_t addr, password = 0;
//Check number of arguments
//int n = lua_gettop(L);
// get addr
size_t size = 0;
const char *p_addr = luaL_checklstring(L, 1, &size);
sscanf(p_addr, "%u", &addr);
// get password
const char *p_pwd = luaL_checklstring(L, 2, &size);
if (size == 0) {
use_pwd = false;
} else {
if (size != 8)
return returnToLuaWithError(L, "Wrong size of password, got %zu , expected 8", size);
sscanf(p_pwd, "%08x", &password);
use_pwd = true;
}
PrintAndLogEx(DEBUG, "Addr %u", addr);
if (use_pwd)
PrintAndLogEx(DEBUG, " Pwd %08X", password);
uint32_t word = 0;
int res = EM4x05ReadWord_ext(addr, password, use_pwd, &word);
if (res != PM3_SUCCESS) {
return returnToLuaWithError(L, "Failed to read EM4x05 data");
}
lua_pushinteger(L, word);
return 1;
}
//
static int l_ndefparse(lua_State *L) {
@ -1203,13 +1244,13 @@ static int l_cwd(lua_State *L) {
// ref: https://github.com/RfidResearchGroup/proxmark3/issues/891
// redirect LUA's print to Proxmark3 PrintAndLogEx
static int l_printandlogex(lua_State *L) {
int n = lua_gettop(L);
for (int i = 1; i <= n; i++) {
if (lua_isstring(L, i)) {
PrintAndLogEx(NORMAL, "%s", lua_tostring(L, i));
PrintAndLogEx(NORMAL, "%s\t" NOLF, lua_tostring(L, i));
}
}
PrintAndLogEx(NORMAL, "");
return 0;
}
@ -1278,6 +1319,7 @@ int set_pm3_libraries(lua_State *L) {
{"ewd", l_ewd},
{"ud", l_ud},
{"rem", l_remark},
{"em4x05_read", l_em4x05_read},
{NULL, NULL}
};

View file

@ -39,11 +39,11 @@ session_arg_t session;
double CursorScaleFactor = 1;
char CursorScaleFactorUnit[11] = {0};
int PlotGridX = 0, PlotGridY = 0, PlotGridXdefault = 64, PlotGridYdefault = 64;
double 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)
static bool flushAfterWrite = 0;
int GridOffset = 0;
double GridOffset = 0;
bool GridLocked = false;
bool showDemod = true;
@ -305,6 +305,9 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
pthread_mutex_lock(&print_lock);
bool linefeed = true;
if (logging && session.incognito) {
logging = 0;
}
if ((g_printAndLog & PRINTANDLOG_LOG) && logging && !logfile) {
char *my_logfile_path = NULL;
char filename[40];
@ -356,7 +359,7 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
va_start(argptr, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, argptr);
va_end(argptr);
if (buffer[strlen(buffer) - 1] == NOLF[0]) {
if (strlen(buffer) > 0 && buffer[strlen(buffer) - 1] == NOLF[0]) {
linefeed = false;
buffer[strlen(buffer) - 1] = 0;
}

View file

@ -40,6 +40,8 @@ typedef struct {
bool window_changed; // track if plot/overlay pos/size changed to save on exit
qtWindow_t plot;
qtWindow_t overlay;
bool overlay_sliders;
bool incognito;
// char *defaultPaths[spItemCount]; // Array should allow loop searching for files
clientdebugLevel_t client_debug_level;
// uint8_t device_debug_level;

View file

@ -708,7 +708,7 @@ bool HIDTryUnpack(wiegand_message_t *packed, bool ignore_parity) {
}
++i;
}
if (result == false) {
if (result == false && packed->Length) {
PrintAndLogEx(SUCCESS, "Unknown. Bit len %d", packed->Length);
}

View file

@ -191,7 +191,7 @@ void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8
crc = crc16_kermit(d, n);
break;
case CRC_11784:
crc = crc16_fdx(d, n);
crc = crc16_fdxb(d, n);
break;
case CRC_LEGIC:
// TODO
@ -225,7 +225,7 @@ uint16_t Crc16ex(CrcType_t ct, const uint8_t *d, size_t n) {
case CRC_KERMIT:
return crc16_kermit(d, n);
case CRC_11784:
return crc16_fdx(d, n);
return crc16_fdxb(d, n);
case CRC_LEGIC:
// TODO
return 0;
@ -270,7 +270,7 @@ bool check_crc(CrcType_t ct, const uint8_t *d, size_t n) {
case CRC_KERMIT:
return (crc16_kermit(d, n) == 0);
case CRC_11784:
return (crc16_fdx(d, n) == 0);
return (crc16_fdxb(d, n) == 0);
case CRC_LEGIC:
// TODO
return false;
@ -288,7 +288,7 @@ uint16_t crc16_ccitt(uint8_t const *d, size_t n) {
// FDX-B ISO11784/85) uses KERMIT/CCITT
// poly 0x xx init=0x000 refin=false refout=true xorout=0x0000 ...
uint16_t crc16_fdx(uint8_t const *d, size_t n) {
uint16_t crc16_fdxb(uint8_t const *d, size_t n) {
return crc16_fast(d, n, 0x0000, false, true);
}

View file

@ -44,7 +44,7 @@ bool check_crc(CrcType_t ct, const uint8_t *d, size_t n);
uint16_t crc16_ccitt(uint8_t const *d, size_t n);
// Calculate CRC-16/KERMIT (FDX-B ISO11784/85) LF
uint16_t crc16_fdx(uint8_t const *d, size_t n);
uint16_t crc16_fdxb(uint8_t const *d, size_t n);
// Calculate CRC-16/KERMIT
uint16_t crc16_kermit(uint8_t const *d, size_t n);

View file

@ -1663,6 +1663,7 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr,
return errCnt;
}
*startIdx = start - (*clk / 2);
if (g_debugMode == 2) prnt("DEBUG: (askdemod_ext) Weak wave detected: startIdx %i", *startIdx);
int lastBit; //set first clock check - can go negative

View file

@ -247,6 +247,7 @@ static int g_debuglog_enable = 1;
/*-************************************
* Types
**************************************/
#include <limits.h>
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
# include <stdint.h>
typedef uint8_t BYTE;
@ -256,7 +257,6 @@ typedef int32_t S32;
typedef uint64_t U64;
typedef uintptr_t uptrval;
#else
# include <limits.h>
# if UINT_MAX != 4294967295UL
# error "LZ4 code (when not C++ or C99) assumes that sizeof(int) == 4"
# endif
@ -322,6 +322,8 @@ static void LZ4_write32(void *memPtr, U32 value) { *(U32 *)memPtr = value; }
typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign;
static U16 LZ4_read16(const void *ptr) { return ((const unalign *)ptr)->u16; }
// Tolerate reads on buffer boundary
ATTRIBUTE_NO_SANITIZE_ADDRESS
static U32 LZ4_read32(const void *ptr) { return ((const unalign *)ptr)->u32; }
static reg_t LZ4_read_ARCH(const void *ptr) { return ((const unalign *)ptr)->uArch; }
@ -1182,13 +1184,14 @@ _last_literals:
if (outputDirective == fillOutput) {
/* adapt lastRun to fill 'dst' */
assert(olimit >= op);
lastRun = (size_t)(olimit - op) - 1;
lastRun -= (lastRun + 240) / 255;
lastRun = (size_t)(olimit - op) - 1/*token*/;
lastRun -= (lastRun + 256 - RUN_MASK) / 256; /*additional length tokens*/
} else {
assert(outputDirective == limitedOutput);
return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */
}
}
DEBUGLOG(6, "Final literal run : %i literals", (int)lastRun);
if (lastRun >= RUN_MASK) {
size_t accumulator = lastRun - RUN_MASK;
*op++ = RUN_MASK << ML_BITS;
@ -1666,7 +1669,9 @@ typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive;
*/
typedef enum { loop_error = -2, initial_error = -1, ok = 0 } variable_length_error;
LZ4_FORCE_INLINE unsigned
read_variable_length(const BYTE **ip, const BYTE *lencheck, int loop_check, int initial_check, variable_length_error *error) {
read_variable_length(const BYTE **ip, const BYTE *lencheck,
int loop_check, int initial_check,
variable_length_error *error) {
U32 length = 0;
U32 s;
if (initial_check && unlikely((*ip) >= lencheck)) { /* overflow detection */
@ -1767,7 +1772,7 @@ LZ4_decompress_generic(
/* decode literal length */
if (length == RUN_MASK) {
variable_length_error error = ok;
length += read_variable_length(&ip, iend - RUN_MASK, endOnInput, endOnInput, &error);
length += read_variable_length(&ip, iend - RUN_MASK, (int)endOnInput, (int)endOnInput, &error);
if (error == initial_error) { goto _output_error; }
if ((safeDecode) && unlikely((uptrval)(op) + length < (uptrval)(op))) { goto _output_error; } /* overflow detection */
if ((safeDecode) && unlikely((uptrval)(ip) + length < (uptrval)(ip))) { goto _output_error; } /* overflow detection */
@ -1815,7 +1820,7 @@ LZ4_decompress_generic(
if (length == ML_MASK) {
variable_length_error error = ok;
if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */
length += read_variable_length(&ip, iend - LASTLITERALS + 1, endOnInput, 0, &error);
length += read_variable_length(&ip, iend - LASTLITERALS + 1, (int)endOnInput, 0, &error);
if (error != ok) { goto _output_error; }
if ((safeDecode) && unlikely((uptrval)(op) + length < (uptrval)op)) { goto _output_error; } /* overflow detection */
length += MINMATCH;
@ -1844,7 +1849,7 @@ LZ4_decompress_generic(
}
}
if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */
if (checkOffset && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */
/* match starting within external dictionary */
if ((dict == usingExtDict) && (match < lowPrefix)) {
if (unlikely(op + length > oend - LASTLITERALS)) {
@ -1946,7 +1951,7 @@ safe_decode:
/* decode literal length */
if (length == RUN_MASK) {
variable_length_error error = ok;
length += read_variable_length(&ip, iend - RUN_MASK, endOnInput, endOnInput, &error);
length += read_variable_length(&ip, iend - RUN_MASK, (int)endOnInput, (int)endOnInput, &error);
if (error == initial_error) { goto _output_error; }
if ((safeDecode) && unlikely((uptrval)(op) + length < (uptrval)(op))) { goto _output_error; } /* overflow detection */
if ((safeDecode) && unlikely((uptrval)(ip) + length < (uptrval)(ip))) { goto _output_error; } /* overflow detection */
@ -1997,7 +2002,12 @@ safe_literal_copy:
/* We must be on the last sequence (or invalid) because of the parsing limitations
* so check that we exactly consume the input and don't overrun the output buffer.
*/
if ((endOnInput) && ((ip + length != iend) || (cpy > oend))) { goto _output_error; }
if ((endOnInput) && ((ip + length != iend) || (cpy > oend))) {
DEBUGLOG(6, "should have been last run of literals")
DEBUGLOG(6, "ip(%p) + length(%i) = %p != iend (%p)", ip, (int)length, ip + length, iend);
DEBUGLOG(6, "or cpy(%p) > oend(%p)", cpy, oend);
goto _output_error;
}
}
memmove(op, ip, length); /* supports overlapping memory regions; only matters for in-place decompression scenarios */
ip += length;
@ -2027,7 +2037,7 @@ safe_literal_copy:
_copy_match:
if (length == ML_MASK) {
variable_length_error error = ok;
length += read_variable_length(&ip, iend - LASTLITERALS + 1, endOnInput, 0, &error);
length += read_variable_length(&ip, iend - LASTLITERALS + 1, (int)endOnInput, 0, &error);
if (error != ok) goto _output_error;
if ((safeDecode) && unlikely((uptrval)(op) + length < (uptrval)op)) goto _output_error; /* overflow detection */
}

View file

@ -42,6 +42,11 @@ extern "C" {
/* --- Dependency --- */
#include <stddef.h> /* size_t */
#if defined(__clang__) || defined (__GNUC__)
# define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#else
# define ATTRIBUTE_NO_SANITIZE_ADDRESS
#endif
/**
Introduction
@ -100,7 +105,7 @@ extern "C" {
/*------ Version ------*/
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
#define LZ4_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)

View file

@ -268,7 +268,7 @@ LZ4HC_InsertAndGetWiderMatch(
DEBUGLOG(7, "First match at index %u / %u (lowestMatchIndex)",
matchIndex, lowestMatchIndex);
while ((matchIndex >= lowestMatchIndex) && (nbAttempts)) {
while ((matchIndex >= lowestMatchIndex) && (nbAttempts > 0)) {
int matchLength = 0;
nbAttempts--;
assert(matchIndex < ipIndex);
@ -424,7 +424,7 @@ LZ4HC_InsertAndGetWiderMatch(
} /* while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) */
if (dict == usingDictCtxHc
&& nbAttempts
&& nbAttempts > 0
&& ipIndex - lowestMatchIndex < LZ4_DISTANCE_MAX) {
size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->base);
U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)];
@ -497,7 +497,7 @@ LZ4_FORCE_INLINE int LZ4HC_encodeSequence(
U32 const cost = 1 + llAdd + ll + 2 + mlAdd;
if (start == NULL) start = *anchor; /* only works for single segment */
/* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */
DEBUGLOG(6, "pos:%7u -- literals:%3u, match:%4i, offset:%5u, cost:%3u + %u",
DEBUGLOG(6, "pos:%7u -- literals:%4u, match:%4i, offset:%5u, cost:%4u + %5u",
pos,
(U32)(*ip - *anchor), matchLength, (U32)(*ip - match),
cost, totalCost);
@ -506,7 +506,13 @@ LZ4_FORCE_INLINE int LZ4HC_encodeSequence(
/* Encode Literal length */
length = (size_t)(*ip - *anchor);
if ((limit) && ((*op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1; /* Check output limit */
LZ4_STATIC_ASSERT(notLimited == 0);
/* Check output limit */
if (limit && ((*op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) {
DEBUGLOG(6, "Not enough room to write %i literals (%i bytes remaining)",
(int)length, (int)(oend - *op));
return 1;
}
if (length >= RUN_MASK) {
size_t len = length - RUN_MASK;
*token = (RUN_MASK << ML_BITS);
@ -528,7 +534,10 @@ LZ4_FORCE_INLINE int LZ4HC_encodeSequence(
/* Encode MatchLength */
assert(matchLength >= MINMATCH);
length = (size_t)matchLength - MINMATCH;
if ((limit) && (*op + (length / 255) + (1 + LASTLITERALS) > oend)) return 1; /* Check output limit */
if (limit && (*op + (length / 255) + (1 + LASTLITERALS) > oend)) {
DEBUGLOG(6, "Not enough room to write match length");
return 1; /* Check output limit */
}
if (length >= ML_MASK) {
*token += ML_MASK;
length -= ML_MASK;
@ -552,7 +561,7 @@ LZ4_FORCE_INLINE int LZ4HC_compress_hashChain(
char *const dest,
int *srcSizePtr,
int const maxOutputSize,
unsigned maxNbAttempts,
int maxNbAttempts,
const limitedOutput_directive limit,
const dictCtx_directive dict
) {
@ -658,7 +667,11 @@ _Search3:
if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow;
ip = start2;
optr = op;
if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml2, ref2, limit, oend)) goto _dest_overflow;
if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml2, ref2, limit, oend)) {
ml = ml2;
ref = ref2;
goto _dest_overflow;
}
continue;
}
@ -735,17 +748,18 @@ _last_literals:
/* Encode Last Literals */
{
size_t lastRunSize = (size_t)(iend - anchor); /* literals */
size_t litLength = (lastRunSize + 255 - RUN_MASK) / 255;
size_t const totalSize = 1 + litLength + lastRunSize;
size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;
size_t const totalSize = 1 + llAdd + lastRunSize;
if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */
if (limit && (op + totalSize > oend)) {
if (limit == limitedOutput) return 0; /* Check output limit */
if (limit == limitedOutput) return 0;
/* adapt lastRunSize to fill 'dest' */
lastRunSize = (size_t)(oend - op) - 1;
litLength = (lastRunSize + 255 - RUN_MASK) / 255;
lastRunSize -= litLength;
lastRunSize = (size_t)(oend - op) - 1 /*token*/;
llAdd = (lastRunSize + 256 - RUN_MASK) / 256;
lastRunSize -= llAdd;
}
ip = anchor + lastRunSize;
DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize);
ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */
if (lastRunSize >= RUN_MASK) {
size_t accumulator = lastRunSize - RUN_MASK;
@ -765,9 +779,27 @@ _last_literals:
_dest_overflow:
if (limit == fillOutput) {
/* Assumption : ip, anchor, ml and ref must be set correctly */
size_t const ll = (size_t)(ip - anchor);
size_t const ll_addbytes = (ll + 240) / 255;
size_t const ll_totalCost = 1 + ll_addbytes + ll;
BYTE *const maxLitPos = oend - 3; /* 2 for offset, 1 for token */
DEBUGLOG(6, "Last sequence overflowing");
op = optr; /* restore correct out pointer */
if (op + ll_totalCost <= maxLitPos) {
/* ll validated; now adjust match length */
size_t const bytesLeftForMl = (size_t)(maxLitPos - (op + ll_totalCost));
size_t const maxMlSize = MINMATCH + (ML_MASK - 1) + (bytesLeftForMl * 255);
assert(maxMlSize < INT_MAX);
assert(ml >= 0);
if ((size_t)ml > maxMlSize) ml = (int)maxMlSize;
if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ml >= MFLIMIT) {
LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, notLimited, oend);
}
}
goto _last_literals;
}
/* compression failed */
return 0;
}
@ -794,7 +826,7 @@ LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal(
typedef enum { lz4hc, lz4opt } lz4hc_strat_e;
typedef struct {
lz4hc_strat_e strat;
U32 nbSearches;
int nbSearches;
U32 targetLength;
} cParams_t;
static const cParams_t clTable[LZ4HC_CLEVEL_MAX + 1] = {
@ -813,7 +845,8 @@ LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal(
{ lz4opt, 16384, LZ4_OPT_NUM }, /* 12==LZ4HC_CLEVEL_MAX */
};
DEBUGLOG(4, "LZ4HC_compress_generic(ctx=%p, src=%p, srcSize=%d)", ctx, src, *srcSizePtr);
DEBUGLOG(4, "LZ4HC_compress_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)",
ctx, src, *srcSizePtr, limit);
if (limit == fillOutput && dstCapacity < 1) return 0; /* Impossible to store anything */
if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size (too large or negative) */
@ -834,7 +867,7 @@ LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal(
assert(cParam.strat == lz4opt);
result = LZ4HC_compress_optimal(ctx,
src, dst, srcSizePtr, dstCapacity,
(int)cParam.nbSearches, cParam.targetLength, limit,
cParam.nbSearches, cParam.targetLength, limit,
cLevel == LZ4HC_CLEVEL_MAX, /* ultra mode */
dict, favor);
}
@ -967,10 +1000,12 @@ int LZ4_compress_HC_destSize(void *state, const char *source, char *dest, int *s
**************************************/
/* allocation */
LZ4_streamHC_t *LZ4_createStreamHC(void) {
LZ4_streamHC_t *const LZ4_streamHCPtr = (LZ4_streamHC_t *)ALLOC(sizeof(LZ4_streamHC_t));
if (LZ4_streamHCPtr == NULL) return NULL;
LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); /* full initialization, malloc'ed buffer can be full of garbage */
return LZ4_streamHCPtr;
LZ4_streamHC_t *const state = (LZ4_streamHC_t *)ALLOC(sizeof(LZ4_streamHC_t));
if (LZ4_initStreamHC(state, sizeof(*state)) == NULL) {
free(state);
return NULL;
}
return state;
}
int LZ4_freeStreamHC(LZ4_streamHC_t *LZ4_streamHCPtr) {
@ -980,7 +1015,10 @@ int LZ4_freeStreamHC(LZ4_streamHC_t *LZ4_streamHCPtr) {
return 0;
}
// Skip AddressSanitizer which breaks compilation strangely on
// lz4/lz4hc.c: error: writing 2 bytes into a region of size 1 [-Werror=stringop-overflow=]
// | LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = 0;
ATTRIBUTE_NO_SANITIZE_ADDRESS
LZ4_streamHC_t *LZ4_initStreamHC(void *buffer, size_t size) {
LZ4_streamHC_t *const LZ4_streamHCPtr = (LZ4_streamHC_t *)buffer;
if (buffer == NULL) return NULL;
@ -1084,8 +1122,8 @@ static int LZ4_compressHC_continue_generic(LZ4_streamHC_t *LZ4_streamHCPtr,
int *srcSizePtr, int dstCapacity,
limitedOutput_directive limit) {
LZ4HC_CCtx_internal *const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
DEBUGLOG(4, "LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d)",
LZ4_streamHCPtr, src, *srcSizePtr);
DEBUGLOG(5, "LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)",
LZ4_streamHCPtr, src, *srcSizePtr, limit);
assert(ctxPtr != NULL);
/* auto-init if forgotten */
if (ctxPtr->base == NULL) LZ4HC_init_internal(ctxPtr, (const BYTE *) src);
@ -1301,6 +1339,8 @@ static int LZ4HC_compress_optimal(LZ4HC_CCtx_internal *ctx,
BYTE *op = (BYTE *) dst;
BYTE *opSaved = (BYTE *) dst;
BYTE *oend = op + dstCapacity;
int ovml = MINMATCH; /* overflow - last sequence */
const BYTE *ovref = NULL;
/* init */
#ifdef LZ4HC_HEAPMODE
@ -1312,7 +1352,6 @@ static int LZ4HC_compress_optimal(LZ4HC_CCtx_internal *ctx,
if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM - 1;
/* Main Loop */
assert(ip - anchor < LZ4_MAX_INPUT_SIZE);
while (ip <= mflimit) {
int const llen = (int)(ip - anchor);
int best_mlen, best_off;
@ -1326,8 +1365,11 @@ static int LZ4HC_compress_optimal(LZ4HC_CCtx_internal *ctx,
int const firstML = firstMatch.len;
const BYTE *const matchPos = ip - firstMatch.off;
opSaved = op;
if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, matchPos, limit, oend)) /* updates ip, op and anchor */
if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, matchPos, limit, oend)) { /* updates ip, op and anchor */
ovml = firstML;
ovref = matchPos;
goto _dest_overflow;
}
continue;
}
@ -1516,18 +1558,21 @@ encode: /* cur, last_match_pos, best_mlen, best_off must be set */
assert(ml >= MINMATCH);
assert((offset >= 1) && (offset <= LZ4_DISTANCE_MAX));
opSaved = op;
if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ip - offset, limit, oend)) /* updates ip, op and anchor */
if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ip - offset, limit, oend)) { /* updates ip, op and anchor */
ovml = ml;
ovref = ip - offset;
goto _dest_overflow;
}
}
}
} /* while (ip <= mflimit) */
_last_literals:
/* Encode Last Literals */
{
size_t lastRunSize = (size_t)(iend - anchor); /* literals */
size_t litLength = (lastRunSize + 255 - RUN_MASK) / 255;
size_t const totalSize = 1 + litLength + lastRunSize;
size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;
size_t const totalSize = 1 + llAdd + lastRunSize;
if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */
if (limit && (op + totalSize > oend)) {
if (limit == limitedOutput) { /* Check output limit */
@ -1535,11 +1580,12 @@ _last_literals:
goto _return_label;
}
/* adapt lastRunSize to fill 'dst' */
lastRunSize = (size_t)(oend - op) - 1;
litLength = (lastRunSize + 255 - RUN_MASK) / 255;
lastRunSize -= litLength;
lastRunSize = (size_t)(oend - op) - 1 /*token*/;
llAdd = (lastRunSize + 256 - RUN_MASK) / 256;
lastRunSize -= llAdd;
}
ip = anchor + lastRunSize;
DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize);
ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */
if (lastRunSize >= RUN_MASK) {
size_t accumulator = lastRunSize - RUN_MASK;
@ -1560,7 +1606,27 @@ _last_literals:
_dest_overflow:
if (limit == fillOutput) {
/* Assumption : ip, anchor, ovml and ovref must be set correctly */
size_t const ll = (size_t)(ip - anchor);
size_t const ll_addbytes = (ll + 240) / 255;
size_t const ll_totalCost = 1 + ll_addbytes + ll;
BYTE *const maxLitPos = oend - 3; /* 2 for offset, 1 for token */
DEBUGLOG(6, "Last sequence overflowing (only %i bytes remaining)", (int)(oend - 1 - opSaved));
op = opSaved; /* restore correct out pointer */
if (op + ll_totalCost <= maxLitPos) {
/* ll validated; now adjust match length */
size_t const bytesLeftForMl = (size_t)(maxLitPos - (op + ll_totalCost));
size_t const maxMlSize = MINMATCH + (ML_MASK - 1) + (bytesLeftForMl * 255);
assert(maxMlSize < INT_MAX);
assert(ovml >= 0);
if ((size_t)ovml > maxMlSize) ovml = (int)maxMlSize;
if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ovml >= MFLIMIT) {
DEBUGLOG(6, "Space to end : %i + ml (%i)", (int)((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1), ovml);
DEBUGLOG(6, "Before : ip = %p, anchor = %p", ip, anchor);
LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ovml, ovref, notLimited, oend);
DEBUGLOG(6, "After : ip = %p, anchor = %p", ip, anchor);
}
}
goto _last_literals;
}
_return_label:

View file

@ -79,22 +79,20 @@ ifneq (,$(PLATFORM_EXTRAS_TMP))
endif
# common LF support
PLATFORM_DEFS += \
-DWITH_LF \
-DWITH_HITAG \
-DWITH_EM4x50
PLATFORM_DEFS += -DWITH_LF
PLATFORM_DEFS += -DWITH_HITAG
PLATFORM_DEFS += -DWITH_EM4x50
# common HF support
PLATFORM_DEFS += \
-DWITH_ISO15693 \
-DWITH_LEGICRF \
-DWITH_ISO14443b \
-DWITH_ISO14443a \
-DWITH_ICLASS \
-DWITH_FELICA \
-DWITH_NFCBARCODE \
-DWITH_HFSNIFF \
-DWITH_HFPLOT
PLATFORM_DEFS += -DWITH_ISO15693
PLATFORM_DEFS += -DWITH_LEGICRF
PLATFORM_DEFS += -DWITH_ISO14443b
PLATFORM_DEFS += -DWITH_ISO14443a
PLATFORM_DEFS += -DWITH_ICLASS
PLATFORM_DEFS += -DWITH_FELICA
PLATFORM_DEFS += -DWITH_NFCBARCODE
PLATFORM_DEFS += -DWITH_HFSNIFF
PLATFORM_DEFS += -DWITH_HFPLOT
# Standalone mode

View file

@ -46,9 +46,10 @@ Reverse permute iCLASS master key
```
Options
---
r reverse permuted key
-r --reverse : reverse permuted key
--key <bytes> : input key
pm3 --> hf iclass permute r 3F90EBF0910F7B6F
pm3 --> hf iclass permute --reverse --key 3F90EBF0910F7B6F
```
iCLASS Reader
@ -369,12 +370,14 @@ pm3 --> lf hid demod
Simulate Prox card
```
pm3 --> lf hid sim 200670012d
pm3 --> lf hid sim -r 200670012d
pm3 --> lf hid sim -w H10301 --fc 10 --cn 1337
```
Clone Prox to T5577 card
```
pm3 --> lf hid clone 200670012d
pm3 --> lf hid clone -r 200670012d
pm3 --> lf hid clone -w H10301 --fc 10 --cn 1337
```
Brute force HID reader
@ -538,12 +541,12 @@ pm3 --> data samples <size>
Save samples to file
```
pm3 --> data save <filename>
pm3 --> data save -f <filename>
```
Load samples from file
```
pm3 --> data load <filename>
pm3 --> data load -f <filename>
```
## Lua Scripts

View file

@ -184,25 +184,37 @@ arg_get_u64_def(\<context\>, \<opt index\>, \<default value\>);
cardnumber = arg_get_u64_def(ctx, 2, 0);
**hex option**
**hex option with return**
CLIGetHexWithReturn(\<context\>, \<opt index\>, \<store variable\>, \<ptr to stored length\>);
?? as an array of uint_8 ??
If failed to retrieve hexbuff, it will exit fct
uint8_t aid[2] = {0};
int aidlen;
CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
**hex option returning ???**
**hex option**
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 ???
**string option**
**string option return**
CLIGetStrWithReturn(\<context\>,\<opt index\>, \<unsigned char \*\>, \<int \*\>);
If failed to retrieve string, it will exit fct
uint8_t Buffer[100];
int BufLen;
CLIGetStrWithReturn(ctx,7, Buffer, &BufLen);
uint8_t buffer[100];
int slen = 0;
CLIGetStrWithReturn(ctx, 1, buffer, &slen);
**string option**
Getting a char array
int slen = 0;
char format[16] = {0};
int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &slen);
quick test : seem res == 0, then ok. compare res == slen to see how many chars

View file

@ -76,11 +76,12 @@ Current usages:
* `void SpinDelayUs(int us)`
* `void SpinDelay(int ms)` based on SpinDelayUs
* `void SpinDelayUsPrecision(int us)`
Busy wait based on 46.875 kHz PWM Channel 0, 21.3 us precision
WARNING: timer can't measure more than 1.39 s
Busy wait based on 46.875 kHz PWM Channel 0
* 21.3 us precision and maximum 1.39 s
* *Precision* variant: 0.7 us precision and maximum 43 ms
## Occasional TC0+TC1 / CountUS functions
@ -98,7 +99,7 @@ Maximal value: 0x7fffffff = 2147 s
Can't be used at the same time as CountSspClk or Ticks functions.
## Occasional TC0+TC1 SSP_CLK from FPGA / CountSspClk functions
## Occasional TC0+TC1+TC2 SSP_CLK from FPGA / CountSspClk functions
cf `armsrc/ticks.c`

View file

@ -72,7 +72,7 @@ lf config s 10000 t 20
lf t55xx sniff
-- if you have a save trace from before, try
data load xxxxxxx.pm3
data load -f xxxxxxx.pm3
lf t55xx sniff 1
```

View file

@ -10,9 +10,12 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`help `|Y |`This help. Use '<command> help' for details of a particular command.`
|`auto `|N |`Automated detection process for unknown tags`
|`clear `|Y |`clear screen`
|`help `|Y |`This help. Use '<command> help' for details of a particular command.`
|`hints `|Y |`Turn hints on / off`
|`msleep `|Y |`Add a pause in milliseconds`
|`pref `|Y |`Edit preferences`
|`rem `|Y |`Add a text line in log file`
|`quit `|Y |``
|`exit `|Y |`Exit program`
@ -34,6 +37,7 @@ Check column "offline" for their availability.
|`analyse a `|Y |`num bits test`
|`analyse nuid `|Y |`create NUID from 7byte UID`
|`analyse demodbuff `|Y |`Load binary string to demodbuffer`
|`analyse freq `|Y |`Calc wave lengths`
### data
@ -43,42 +47,45 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`data help `|Y |`This help`
|`data askedgedetect `|Y |`[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)`
|`data autocorr `|Y |`[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)`
|`data biphaserawdecode `|Y |`[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)`
|`data bin2hex `|Y |`<digits> -- Converts binary to hexadecimal`
|`data bitsamples `|N |`Get raw samples as bitstring`
|`data buffclear `|Y |`Clears bigbuff on deviceside and graph window`
|`data convertbitstream `|Y |`Convert GraphBuffer's 0/1 values to 127 / -127`
|`data dec `|Y |`Decimate samples`
|`data detectclock `|Y |`[<a|f|n|p>] Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer`
|`data biphaserawdecode `|Y |`Biphase decode bin stream in DemodBuffer`
|`data detectclock `|Y |`Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer`
|`data fsktonrz `|Y |`Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)`
|`data getbitstream `|Y |`Convert GraphBuffer's >=1 values to 1 and <1 to 0`
|`data grid `|Y |`<x> <y> -- overlay grid on graph window, use zero value to turn off either`
|`data hexsamples `|N |`<bytes> [<offset>] -- Dump big buffer as hex bytes`
|`data hex2bin `|Y |`<hexadecimal> -- Converts hexadecimal to binary`
|`data manrawdecode `|Y |`Manchester decode binary stream in DemodBuffer`
|`data modulation `|Y |`Identify LF signal for clock and modulation`
|`data rawdemod `|Y |`Demodulate the data in the GraphBuffer and output binary`
|`data askedgedetect `|Y |`[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)`
|`data autocorr `|Y |`Autocorrelation over window`
|`data dirthreshold `|Y |`<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev.`
|`data decimate `|Y |`Decimate samples`
|`data undecimate `|Y |`Un-decimate samples`
|`data hide `|Y |`Hide graph window`
|`data hpf `|Y |`Remove DC offset from trace`
|`data load `|Y |`<filename> -- Load trace (to graph window`
|`data iir `|Y |`apply IIR buttersworth filter on plotdata`
|`data grid `|Y |`<x> <y> -- overlay grid on graph window, use zero value to turn off either`
|`data ltrim `|Y |`<samples> -- Trim samples from left of trace`
|`data rtrim `|Y |`<location to end trace> -- Trim samples from right of trace`
|`data mtrim `|Y |`<start> <stop> -- Trim out samples from the specified start to the specified stop`
|`data manrawdecode `|Y |`[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer`
|`data norm `|Y |`Normalize max/min to +/-128`
|`data plot `|Y |`Show graph window (hit 'h' in window for keystroke help)`
|`data printdemodbuffer `|Y |`[x] [o] <offset> [l] <length> -- print the data in the DemodBuffer - 'x' for hex output`
|`data rawdemod `|Y |`[modulation] ... <options> -see help (h option) -- Demodulate the data in the GraphBuffer and output binary`
|`data samples `|N |`[512 - 40000] -- Get raw samples for graph window (GraphBuffer)`
|`data save `|Y |`Save trace (from graph window)`
|`data rtrim `|Y |`<location to end trace> -- Trim samples from right of trace`
|`data setgraphmarkers `|Y |`[orange_marker] [blue_marker] (in graph window)`
|`data scale `|Y |`<int> -- Set cursor display scale in carrier frequency expressed in kHz`
|`data setdebugmode `|Y |`<0|1|2> -- Set Debugging Level on client side`
|`data shiftgraphzero `|Y |`<shift> -- Shift 0 for Graphed wave + or - shift value`
|`data dirthreshold `|Y |`<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev.`
|`data tune `|N |`Get hw tune samples for graph window`
|`data undec `|Y |`Un-decimate samples by 2`
|`data timescale `|Y |`Set a timescale to get a differential reading between the yellow and purple markers as time duration
`
|`data zerocrossings `|Y |`Count time between zero-crossings`
|`data iir `|Y |`apply IIR buttersworth filter on plotdata`
|`data convertbitstream `|Y |`Convert GraphBuffer's 0/1 values to 127 / -127`
|`data getbitstream `|Y |`Convert GraphBuffer's >=1 values to 1 and <1 to 0`
|`data bin2hex `|Y |`Converts binary to hexadecimal`
|`data bitsamples `|N |`Get raw samples as bitstring`
|`data clear `|Y |`Clears bigbuf on deviceside and graph window`
|`data hexsamples `|N |`<bytes> [<offset>] -- Dump big buffer as hex bytes`
|`data hex2bin `|Y |`Converts hexadecimal to binary`
|`data load `|Y |`Load contents of file into graph window`
|`data ndef `|Y |`Decode NDEF records`
|`data print `|Y |`print the data in the DemodBuffer`
|`data samples `|N |`[512 - 40000] -- Get raw samples for graph window (GraphBuffer)`
|`data save `|Y |`Save signal trace data (from graph window)`
|`data setdebugmode `|Y |`<0|1|2> -- Set Debugging Level on client side`
|`data tune `|N |`Measure tuning of device antenna. Results shown in graph window`
### emv
@ -111,6 +118,7 @@ Check column "offline" for their availability.
|------- |------- |-----------
|`hf help `|Y |`This help`
|`hf list `|Y |`List protocol data in trace buffer`
|`hf plot `|N |`Plot signal`
|`hf tune `|N |`Continuously measure HF antenna tuning`
|`hf search `|Y |`Search for known HF tags`
|`hf sniff `|N |`<samples to skip (10000)> <triggers to skip (1)> Generic HF Sniff`
@ -133,6 +141,7 @@ Check column "offline" for their availability.
|`hf 14a chaining `|N |`Control ISO 14443-4 input chaining`
|`hf 14a raw `|N |`Send raw hex data to tag`
|`hf 14a antifuzz `|N |`Fuzzing the anticollision phase. Warning! Readers may react strange`
|`hf 14a config `|N |`Configure 14a settings (use with caution)`
### hf 14b
@ -142,9 +151,11 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`hf 14b help `|Y |`This help`
|`hf 14b apdu `|N |`Send ISO 14443-4 APDU to tag`
|`hf 14b dump `|N |`Read all memory pages of an ISO14443-B tag, save to file`
|`hf 14b info `|N |`Tag information`
|`hf 14b list `|Y |`List ISO 14443B history`
|`hf 14b ndef `|N |`Read NDEF file on tag`
|`hf 14b raw `|N |`Send raw hex data to tag`
|`hf 14b reader `|N |`Act as a 14443B reader to identify a tag`
|`hf 14b sim `|N |`Fake ISO 14443B tag`
@ -160,22 +171,22 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`hf 15 help `|Y |`This help`
|`hf 15 list `|Y |`List ISO15693 history`
|`hf 15 demod `|Y |`Demodulate ISO15693 from tag`
|`hf 15 dump `|N |`Read all memory pages of an ISO15693 tag, save to file`
|`hf 15 info `|N |`Tag information`
|`hf 15 sniff `|N |`Sniff ISO15693 traffic`
|`hf 15 raw `|N |`Send raw hex data to tag`
|`hf 15 read `|N |`Read a block`
|`hf 15 reader `|N |`Act like an ISO15693 reader`
|`hf 15 readmulti `|N |`Reads multiple Blocks`
|`hf 15 restore `|N |`Restore from file to all memory pages of an ISO15693 tag`
|`hf 15 samples `|N |`Acquire Samples as Reader (enables carrier, sends inquiry)`
|`hf 15 sim `|N |`Fake an ISO15693 tag`
|`hf 15 write `|N |`Write a block`
|`hf 15 findafi `|N |`Brute force AFI of an ISO15693 tag`
|`hf 15 writeafi `|N |`Writes the AFI on an ISO15693 tag`
|`hf 15 writedsfid `|N |`Writes the DSFID on an ISO15693 tag`
|`hf 15 info `|N |`Tag information`
|`hf 15 list `|Y |`List ISO15693 history`
|`hf 15 raw `|N |`Send raw hex data to tag`
|`hf 15 reader `|N |`Act like an ISO15693 reader`
|`hf 15 record `|N |`Record Samples (ISO15693)`
|`hf 15 restore `|N |`Restore from file to all memory pages of an ISO15693 tag`
|`hf 15 sim `|N |`Fake an ISO15693 tag`
|`hf 15 samples `|N |`Acquire Samples as Reader (enables carrier, sends inquiry)`
|`hf 15 read `|N |`Read a block`
|`hf 15 write `|N |`Write a block`
|`hf 15 readmulti `|N |`Reads multiple Blocks`
|`hf 15 csetuid `|N |`Set UID for magic Chinese card`
@ -201,40 +212,33 @@ Check column "offline" for their availability.
|`hf felica reader `|N |`Act like an ISO18092/FeliCa reader`
|`hf felica sniff `|N |`Sniff ISO 18092/FeliCa traffic`
|`hf felica raw `|N |`Send raw hex data to tag`
|`hf felica rqservice `|N |`verify the existence of Area and Service, and to acquire Key Version.`
|`hf felica rqresponse `|N |`verify the existence of a card and its Mode.`
|`hf felica rdunencrypted`|N |`read Block Data from authentication-not-required Service.`
|`hf felica wrunencrypted`|N |`write Block Data to an authentication-not-required Service.`
|`hf felica rqservice `|N |`verify the existence of Area and Service, and to acquire Key Version.`
|`hf felica rqresponse `|N |`verify the existence of a card and its Mode.`
|`hf felica scsvcode `|N |`acquire Area Code and Service Code.`
|`hf felica rqsyscode `|N |`acquire System Code registered to the card.`
|`hf felica auth1 `|N |`authenticate a card. Start mutual authentication with Auth1`
|`hf felica auth2 `|N |`allow a card to authenticate a Reader/Writer. Complete mutual authentication`
|`hf felica read `|N |`read Block Data from authentication-required Service.`
|`hf felica rqspecver `|N |`acquire the version of card OS.`
|`hf felica resetmode `|N |`reset Mode to Mode 0.`
|`hf felica litesim `|N |`<NDEF2> - only reply to poll request`
|`hf felica litedump `|N |`Wait for and try dumping FelicaLite`
### hf legic
### hf fido
{ LEGIC RFIDs... }
{ FIDO and FIDO2 authenticators... }
|command |offline |description
|------- |------- |-----------
|`hf legic help `|Y |`This help`
|`hf legic reader `|N |`LEGIC Prime Reader UID and tag info`
|`hf legic info `|N |`Display deobfuscated and decoded LEGIC Prime tag data`
|`hf legic dump `|N |`Dump LEGIC Prime tag to binary file`
|`hf legic restore `|N |`Restore a dump file onto a LEGIC Prime tag`
|`hf legic rdmem `|N |`Read bytes from a LEGIC Prime tag`
|`hf legic sim `|N |`Start tag simulator`
|`hf legic write `|N |`Write data to a LEGIC Prime tag`
|`hf legic crc `|Y |`Calculate Legic CRC over given bytes`
|`hf legic eload `|N |`Load binary dump to emulator memory`
|`hf legic esave `|N |`Save emulator memory to binary file`
|`hf legic list `|Y |`List LEGIC history`
|`hf legic wipe `|N |`Wipe a LEGIC Prime tag`
|`hf fido help `|Y |`This help.`
|`hf fido info `|N |`List ISO 14443A history`
|`hf fido info `|N |`Info about FIDO tag.`
|`hf fido reg `|N |`FIDO U2F Registration Message.`
|`hf fido auth `|N |`FIDO U2F Authentication Message.`
|`hf fido make `|N |`FIDO2 MakeCredential command.`
|`hf fido assert `|N |`FIDO2 GetAssertion command.`
### hf iclass
@ -244,26 +248,64 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`hf iclass help `|Y |`This help`
|`hf iclass calcnewkey `|Y |`[options..] Calc diversified keys (blocks 3 & 4) to write new keys`
|`hf iclass chk `|Y |`[options..] Check keys`
|`hf iclass clone `|N |`[options..] Restore a dump file onto a iClass tag`
|`hf iclass decrypt `|Y |`[options..] Decrypt given block data or tag dump file`
|`hf iclass dump `|N |`[options..] Dump iClass tag to file`
|`hf iclass eload `|N |`[f <fname>] Load iClass dump file into emulator memory`
|`hf iclass encrypt `|Y |`[options..] Encrypt given block data`
|`hf iclass dump `|N |`[options..] Dump Picopass / iCLASS tag to file`
|`hf iclass info `|Y |` Tag information`
|`hf iclass list `|Y |` List iClass history`
|`hf iclass list `|Y |` List iclass history`
|`hf iclass rdbl `|N |`[options..] Read Picopass / iCLASS block`
|`hf iclass reader `|N |` Act like an Picopass / iCLASS reader`
|`hf iclass restore `|N |`[options..] Restore a dump file onto a Picopass / iCLASS tag`
|`hf iclass sniff `|N |` Eavesdrop Picopass / iCLASS communication`
|`hf iclass wrbl `|N |`[options..] Write Picopass / iCLASS block`
|`hf iclass chk `|Y |`[options..] Check keys`
|`hf iclass loclass `|Y |`[options..] Use loclass to perform bruteforce reader attack`
|`hf iclass lookup `|Y |`[options..] Uses authentication trace to check for key in dictionary file`
|`hf iclass managekeys `|Y |`[options..] Manage keys to use with iClass`
|`hf iclass permutekey `|N |` Permute function from 'heart of darkness' paper`
|`hf iclass rdbl `|N |`[options..] Read iClass block`
|`hf iclass reader `|N |` Act like an iClass reader`
|`hf iclass readtagfile `|Y |`[options..] Display content from tag dump file`
|`hf iclass replay `|N |`<mac> Read iClass tag via replay attack`
|`hf iclass sim `|N |`[options..] Simulate iClass tag`
|`hf iclass sniff `|N |` Eavesdrop iClass communication`
|`hf iclass wrbl `|N |`[options..] Write iClass block`
|`hf iclass replay `|N |`<mac> Read Picopass / iCLASS tag via replay attack`
|`hf iclass sim `|N |`[options..] Simulate iCLASS tag`
|`hf iclass eload `|N |`[f <fn> ] Load Picopass / iCLASS dump file into emulator memory`
|`hf iclass esave `|N |`[f <fn> ] Save emulator memory to file`
|`hf iclass eview `|N |`[options..] View emulator memory`
|`hf iclass calcnewkey `|Y |`[options..] Calc diversified keys (blocks 3 & 4) to write new keys`
|`hf iclass encrypt `|Y |`[options..] Encrypt given block data`
|`hf iclass decrypt `|Y |`[options..] Decrypt given block data or tag dump file`
|`hf iclass managekeys `|Y |`[options..] Manage keys to use with iclass commands`
|`hf iclass permute `|N |` Permute function from 'heart of darkness' paper`
|`hf iclass view `|Y |`[options..] Display content from tag dump file`
### hf legic
{ LEGIC RFIDs... }
|command |offline |description
|------- |------- |-----------
|`hf legic help `|Y |`This help`
|`hf legic list `|Y |`List LEGIC history`
|`hf legic reader `|N |`LEGIC Prime Reader UID and tag info`
|`hf legic info `|N |`Display deobfuscated and decoded LEGIC Prime tag data`
|`hf legic dump `|N |`Dump LEGIC Prime tag to binary file`
|`hf legic restore `|N |`Restore a dump file onto a LEGIC Prime tag`
|`hf legic rdbl `|N |`Read bytes from a LEGIC Prime tag`
|`hf legic sim `|N |`Start tag simulator`
|`hf legic wrbl `|N |`Write data to a LEGIC Prime tag`
|`hf legic crc `|Y |`Calculate Legic CRC over given bytes`
|`hf legic eload `|Y |`Load binary dump to emulator memory`
|`hf legic esave `|Y |`Save emulator memory to binary file`
|`hf legic wipe `|N |`Wipe a LEGIC Prime tag`
### hf lto
{ LTO Cartridge Memory RFIDs... }
|command |offline |description
|------- |------- |-----------
|`hf lto help `|Y |`This help`
|`hf lto dump `|N |`Dump LTO-CM tag to file`
|`hf lto restore `|N |`Restore dump file to LTO-CM tag`
|`hf lto info `|N |`Tag information`
|`hf lto rdbl `|N |`Read block`
|`hf lto wrbl `|N |`Write block`
|`hf lto list `|Y |`List LTO-CM history`
### hf mf
@ -277,38 +319,43 @@ Check column "offline" for their availability.
|`hf mf darkside `|N |`Darkside attack`
|`hf mf nested `|N |`Nested attack`
|`hf mf hardnested `|Y |`Nested attack for hardened MIFARE Classic cards`
|`hf mf staticnested `|N |`Nested attack against static nonce MIFARE Classic cards`
|`hf mf autopwn `|N |`Automatic key recovery tool for MIFARE Classic`
|`hf mf nack `|N |`Test for MIFARE NACK bug`
|`hf mf chk `|N |`Check keys`
|`hf mf fchk `|N |`Check keys fast, targets all keys on card`
|`hf mf decrypt `|Y |`[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace`
|`hf mf rdbl `|N |`Read MIFARE classic block`
|`hf mf rdsc `|N |`Read MIFARE classic sector`
|`hf mf dump `|N |`Dump MIFARE classic tag to binary file`
|`hf mf restore `|N |`Restore MIFARE classic binary file to BLANK tag`
|`hf mf wrbl `|N |`Write MIFARE classic block`
|`hf mf setmod `|N |`Set MIFARE Classic EV1 load modulation strength`
|`hf mf auth4 `|N |`ISO14443-4 AES authentication`
|`hf mf dump `|N |`Dump MIFARE Classic tag to binary file`
|`hf mf mad `|N |`Checks and prints MAD`
|`hf mf ndef `|N |`Prints NDEF records from card`
|`hf mf personalize `|N |`Personalize UID (MIFARE Classic EV1 only)`
|`hf mf rdbl `|N |`Read MIFARE Classic block`
|`hf mf rdsc `|N |`Read MIFARE Classic sector`
|`hf mf restore `|N |`Restore MIFARE Classic binary file to BLANK tag`
|`hf mf setmod `|N |`Set MIFARE Classic EV1 load modulation strength`
|`hf mf wrbl `|N |`Write MIFARE Classic block`
|`hf mf sim `|N |`Simulate MIFARE card`
|`hf mf ecfill `|N |`Fill simulator memory with help of keys from simulator`
|`hf mf eclr `|N |`Clear simulator memory`
|`hf mf egetblk `|N |`Get simulator memory block`
|`hf mf egetsc `|N |`Get simulator memory sector`
|`hf mf eset `|N |`Set simulator memory block`
|`hf mf ekeyprn `|N |`Print keys from simulator memory`
|`hf mf eload `|N |`Load from file emul dump`
|`hf mf esave `|N |`Save to file emul dump`
|`hf mf ecfill `|N |`Fill simulator memory with help of keys from simulator`
|`hf mf ekeyprn `|N |`Print keys from simulator memory`
|`hf mf eview `|N |`View simulator memory`
|`hf mf csetuid `|N |`Set UID (magic chinese card)`
|`hf mf eset `|N |`Set simulator memory block`
|`hf mf eview `|N |`View emul memory`
|`hf mf cgetblk `|N |`Read block`
|`hf mf cgetsc `|N |`Read sector`
|`hf mf cload `|N |`Load dump`
|`hf mf csave `|N |`Save dump from card into file or emulator`
|`hf mf csetblk `|N |`Write block`
|`hf mf csetuid `|N |`Set UID`
|`hf mf cview `|N |`view card`
|`hf mf cwipe `|N |`Wipe card to default UID/Sectors/Keys`
|`hf mf csetblk `|N |`Write block (magic chinese card)`
|`hf mf cgetblk `|N |`Read block (magic chinese card)`
|`hf mf cgetsc `|N |`Read sector (magic chinese card)`
|`hf mf cload `|N |`Load dump (magic chinese card)`
|`hf mf csave `|N |`Save dump from magic chinese card into file or emulator`
|`hf mf cview `|N |`View card memory (magic chinese card)`
|`hf mf mad `|N |`Checks and prints MAD`
|`hf mf ndef `|N |`Prints NDEF records from card`
|`hf mf gen3uid `|N |`Set UID without manufacturer block`
|`hf mf gen3blk `|N |`Overwrite full manufacturer block`
|`hf mf gen3freeze `|N |`Perma lock further UID changes`
|`hf mf ice `|N |`collect MIFARE Classic nonces to file`
@ -352,6 +399,7 @@ Check column "offline" for their availability.
|`hf mfu gen `|Y |`Generate 3des mifare diversified keys`
|`hf mfu pwdgen `|Y |`Generate pwd from known algos`
|`hf mfu otptear `|N |`Tear-off test on OTP bits`
|`hf mfu ndef `|N |`Prints NDEF records from card`
### hf mfdes
@ -362,36 +410,41 @@ Check column "offline" for their availability.
|------- |------- |-----------
|`hf mfdes help `|Y |`This help`
|`hf mfdes info `|N |`Tag information`
|`hf mfdes list `|Y |`List DESFire (ISO 14443A) history`
|`hf mfdes enum `|N |`Tries enumerate all applications`
|`hf mfdes auth `|N |`Tries a MIFARE DesFire Authentication`
|`hf mfdes getuid `|N |`Get random uid`
|`hf mfdes selectaid `|N |`Select Application ID`
|`hf mfdes createaid `|N |`Create Application ID`
|`hf mfdes deleteaid `|N |`Delete Application ID`
|`hf mfdes createfile `|N |`Create Standard/Backup File`
|`hf mfdes createvaluefile`|N |`Create Value File`
|`hf mfdes createrecordfile`|N |`Create Linear/Cyclic Record File`
|`hf mfdes deletefile `|N |`Create Delete File`
|`hf mfdes clearfile `|N |`Clear record File`
|`hf mfdes readdata `|N |`Read data from standard/backup/record file`
|`hf mfdes writedata `|N |`Write data to standard/backup/record file`
|`hf mfdes getvalue `|N |`Get value of file`
|`hf mfdes changevalue `|N |`Write value of a value file (credit/debit/clear)`
|`hf mfdes changekey `|N |`Change Key`
|`hf mfdes formatpicc `|N |`Format PICC`
|`hf mfdes dump `|N |`Dump all files`
|`hf mfdes chk `|N |`Check keys`
### hf topaz
### hf st
{ TOPAZ (NFC Type 1) RFIDs... }
{ ST Rothult RFIDs... }
|command |offline |description
|------- |------- |-----------
|`hf topaz help `|Y |`This help`
|`hf topaz reader `|N |`Act like a Topaz reader`
|`hf topaz sim `|N |`<UID> -- Simulate Topaz tag`
|`hf topaz sniff `|N |`Sniff Topaz reader-tag communication`
|`hf topaz raw `|N |`Send raw hex data to tag`
|`hf topaz list `|Y |`List Topaz history`
### hf fido
{ FIDO and FIDO2 authenticators... }
|command |offline |description
|------- |------- |-----------
|`hf fido help `|Y |`This help.`
|`hf fido info `|N |`Info about FIDO tag.`
|`hf fido reg `|N |`FIDO U2F Registration Message.`
|`hf fido auth `|N |`FIDO U2F Authentication Message.`
|`hf fido make `|N |`FIDO2 MakeCredential command.`
|`hf fido assert `|N |`FIDO2 GetAssertion command.`
|`hf st help `|Y |`This help`
|`hf st info `|N |`Tag information`
|`hf st list `|Y |`List ISO 14443A/7816 history`
|`hf st ndef `|Y |`read NDEF file on tag`
|`hf st protect `|N |`change protection on tag`
|`hf st pwd `|N |`change password on tag`
|`hf st sim `|N |`Fake ISO 14443A/ST tag`
### hf thinfilm
@ -406,6 +459,31 @@ Check column "offline" for their availability.
|`hf thinfilm sim `|N |`Fake Thinfilm tag`
### hf topaz
{ TOPAZ (NFC Type 1) RFIDs... }
|command |offline |description
|------- |------- |-----------
|`hf topaz help `|Y |`This help`
|`hf topaz list `|Y |`List Topaz history`
|`hf topaz info `|N |`Tag information`
|`hf topaz reader `|N |`Act like a Topaz reader`
|`hf topaz sim `|N |`<UID> -- Simulate Topaz tag`
|`hf topaz sniff `|N |`Sniff Topaz reader-tag communication`
|`hf topaz raw `|N |`Send raw hex data to tag`
### hf waveshare
{ Waveshare NFC ePaper... }
|command |offline |description
|------- |------- |-----------
|`hf waveshare help `|Y |`This help`
|`hf waveshare loadbmp `|N |`Load BMP file to Waveshare NFC ePaper`
### hw
{ Hardware commands... }
@ -426,6 +504,7 @@ Check column "offline" for their availability.
|`hw setmux `|N |`Set the ADC mux to a specific value`
|`hw standalone `|N |`Jump to the standalone mode`
|`hw status `|N |`Show runtime status information about the connected Proxmark3`
|`hw tearoff `|N |`Program a tearoff hook for the next command supporting tearoff`
|`hw tia `|N |`Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider`
|`hw tune `|N |`Measure antenna tuning`
|`hw version `|N |`Show version information about the connected Proxmark3`
@ -460,7 +539,7 @@ Check column "offline" for their availability.
|`lf awid help `|Y |`this help`
|`lf awid demod `|Y |`demodulate an AWID FSK tag from the GraphBuffer`
|`lf awid read `|N |`attempt to read and extract tag data`
|`lf awid clone `|N |`clone AWID tag to T55x7 (or to q5/T5555)`
|`lf awid clone `|N |`clone AWID tag to T55x7 or Q5/T5555`
|`lf awid sim `|N |`simulate AWID tag`
|`lf awid brute `|N |`Bruteforce card number against reader`
|`lf awid watch `|N |`continuously watch for cards. Reader mode`
@ -490,30 +569,32 @@ Check column "offline" for their availability.
|`lf em 410x_brute `|N |`reader bruteforce attack by simulating EM410x tags`
|`lf em 410x_watch `|N |`watches for EM410x 125/134 kHz tags (option 'h' for 134)`
|`lf em 410x_spoof `|N |`watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)`
|`lf em 410x_clone `|N |`write EM410x UID to T5555(Q5) or T55x7 tag`
|`lf em 410x_clone `|N |`write EM410x UID to T55x7 or Q5/T5555 tag`
|`lf em 4x05_demod `|Y |`demodulate a EM4x05/EM4x69 tag from the GraphBuffer`
|`lf em 4x05_dump `|N |`dump EM4x05/EM4x69 tag`
|`lf em 4x05_wipe `|N |`wipe EM4x05/EM4x69 tag`
|`lf em 4x05_info `|N |`tag information EM4x05/EM4x69`
|`lf em 4x05_read `|N |`read word data from EM4x05/EM4x69`
|`lf em 4x05_write `|N |`write word data to EM4x05/EM4x69`
|`lf em 4x50_demod `|Y |`demodulate a EM4x50 tag from the GraphBuffer`
|`lf em 4x50_dump `|N |`dump EM4x50 tag`
|`lf em 4x50_read `|N |`read word data from EM4x50`
|`lf em 4x50_info `|N |`tag information EM4x50`
|`lf em 4x50_write `|N |`write word data to EM4x50`
|`lf em 4x50_write_password`|N |`change passwword of EM4x50 tag`
|`lf em 4x50_read `|N |`read word data from EM4x50`
|`lf em 4x50_wipe `|N |`wipe data from EM4x50`
### lf fdx
### lf fdxb
{ FDX-B RFIDs... }
|command |offline |description
|------- |------- |-----------
|`lf fdx help `|Y |`this help`
|`lf fdx demod `|Y |`demodulate a FDX-B ISO11784/85 tag from the GraphBuffer`
|`lf fdx read `|N |`attempt to read and extract tag data`
|`lf fdx clone `|N |`clone animal ID tag to T55x7 (or to q5/T5555)`
|`lf fdx sim `|N |`simulate Animal ID tag`
|`lf fdxb help `|Y |`this help`
|`lf fdxb demod `|Y |`demodulate a FDX-B ISO11784/85 tag from the GraphBuffer`
|`lf fdxb read `|N |`attempt to read at 134kHz and extract tag data`
|`lf fdxb clone `|N |`clone animal ID tag to T55x7 or Q5/T5555`
|`lf fdxb sim `|N |`simulate Animal ID tag`
### lf gallagher
@ -538,13 +619,13 @@ Check column "offline" for their availability.
|`lf gproxii help `|Y |`this help`
|`lf gproxii demod `|Y |`demodulate a G Prox II tag from the GraphBuffer`
|`lf gproxii read `|N |`attempt to read and extract tag data from the antenna`
|`lf gproxii clone `|N |`clone Guardall tag to T55x7`
|`lf gproxii clone `|N |`clone Guardall tag to T55x7 or Q5/T5555`
|`lf gproxii sim `|N |`simulate Guardall tag`
### lf hid
{ HID RFIDs... }
{ HID Prox RFIDs... }
|command |offline |description
|------- |------- |-----------
@ -570,9 +651,21 @@ Check column "offline" for their availability.
|`lf hitag sim `|N |`Simulate Hitag transponder`
|`lf hitag sniff `|N |`Eavesdrop Hitag communication`
|`lf hitag writer `|N |`Act like a Hitag Writer`
|`lf hitag dump `|N |`Dump Hitag2 tag`
|`lf hitag cc `|N |`Test all challenges`
### lf idteck
{ Idteck RFIDs... }
|command |offline |description
|------- |------- |-----------
|`lf idteck help `|Y |`This help`
|`lf idteck demod `|Y |`Demodulate an Idteck tag from the GraphBuffer`
|`lf idteck read `|N |`Attempt to read and Extract tag data from the antenna`
### lf indala
{ Indala RFIDs... }
@ -583,7 +676,7 @@ Check column "offline" for their availability.
|`lf indala demod `|Y |`demodulate an indala tag (PSK1) from GraphBuffer`
|`lf indala altdemod `|Y |`alternative method to Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)`
|`lf indala read `|N |`read an Indala Prox tag from the antenna`
|`lf indala clone `|N |`clone Indala tag to T55x7`
|`lf indala clone `|N |`clone Indala tag to T55x7 or Q5/T5555`
|`lf indala sim `|N |`simulate Indala tag`
@ -596,7 +689,7 @@ Check column "offline" for their availability.
|`lf io help `|Y |`this help`
|`lf io demod `|Y |`demodulate an IOProx tag from the GraphBuffer`
|`lf io read `|N |`attempt to read and extract tag data`
|`lf io clone `|N |`clone IOProx tag to T55x7 (or to q5/T5555)`
|`lf io clone `|N |`clone IOProx tag to T55x7 or Q5/T5555`
|`lf io sim `|N |`simulate IOProx tag`
|`lf io watch `|N |`continuously watch for cards. Reader mode`
@ -610,7 +703,7 @@ Check column "offline" for their availability.
|`lf jablotron help `|Y |`This help`
|`lf jablotron demod `|Y |`Demodulate an Jablotron tag from the GraphBuffer`
|`lf jablotron read `|N |`Attempt to read and extract tag data from the antenna`
|`lf jablotron clone `|N |`clone jablotron tag to T55x7 (or to q5/T5555)`
|`lf jablotron clone `|N |`clone jablotron tag to T55x7 or Q5/T5555`
|`lf jablotron sim `|N |`simulate jablotron tag`
@ -623,10 +716,23 @@ Check column "offline" for their availability.
|`lf keri help `|Y |`This help`
|`lf keri demod `|Y |`Demodulate an KERI tag from the GraphBuffer`
|`lf keri read `|N |`Attempt to read and extract tag data from the antenna`
|`lf keri clone `|N |`clone KERI tag to T55x7 (or to q5/T5555)`
|`lf keri clone `|N |`clone KERI tag to T55x7 or Q5/T5555`
|`lf keri sim `|N |`simulate KERI tag`
### lf motorola
{ Motorola RFIDs... }
|command |offline |description
|------- |------- |-----------
|`lf motorola help `|Y |`This help`
|`lf motorola demod `|Y |`Demodulate an MOTOROLA tag from the GraphBuffer`
|`lf motorola read `|N |`Attempt to read and extract tag data from the antenna`
|`lf motorola clone `|N |`clone MOTOROLA tag to T55x7`
|`lf motorola sim `|N |`simulate MOTOROLA tag`
### lf nedap
{ Nedap RFIDs... }
@ -637,7 +743,7 @@ Check column "offline" for their availability.
|`lf nedap demod `|Y |`Demodulate Nedap tag from the GraphBuffer`
|`lf nedap generate `|Y |`Generate Nedap bitstream in DemodBuffer`
|`lf nedap read `|N |`Attempt to read and extract tag data from the antenna`
|`lf nedap clone `|N |`Clone Nedap tag to T55x7`
|`lf nedap clone `|N |`Clone Nedap tag to T55x7 or Q5/T5555`
|`lf nedap sim `|N |`Simulate Nedap tag`
@ -663,23 +769,10 @@ Check column "offline" for their availability.
|`lf noralsy help `|Y |`This help`
|`lf noralsy demod `|Y |`Demodulate an Noralsy tag from the GraphBuffer`
|`lf noralsy read `|N |`Attempt to read and extract tag data from the antenna`
|`lf noralsy clone `|N |`clone Noralsy tag to T55x7 (or to q5/T5555)`
|`lf noralsy clone `|N |`clone Noralsy tag to T55x7 or Q5/T5555`
|`lf noralsy sim `|N |`simulate Noralsy tag`
### lf motorola
{ Motorola RFIDs... }
|command |offline |description
|------- |------- |-----------
|`lf motorola help `|Y |`This help`
|`lf motorola demod `|Y |`Demodulate an MOTOROLA tag from the GraphBuffer`
|`lf motorola read `|N |`Attempt to read and extract tag data from the antenna`
|`lf motorola clone `|N |`clone MOTOROLA tag to T55x7`
|`lf motorola sim `|N |`simulate MOTOROLA tag`
### lf pac
{ PAC/Stanley RFIDs... }
@ -725,8 +818,9 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`lf presco help `|Y |`This help`
|`lf presco demod `|Y |`demodulate Presco tag from the GraphBuffer`
|`lf presco read `|N |`Attempt to read and Extract tag data`
|`lf presco clone `|N |`clone presco tag to T55x7 (or to q5/T5555)`
|`lf presco clone `|N |`clone presco tag to T55x7 or Q5/T5555`
|`lf presco sim `|N |`simulate presco tag`
@ -739,7 +833,7 @@ Check column "offline" for their availability.
|`lf pyramid help `|Y |`this help`
|`lf pyramid demod `|Y |`demodulate a Pyramid FSK tag from the GraphBuffer`
|`lf pyramid read `|N |`attempt to read and extract tag data`
|`lf pyramid clone `|N |`clone pyramid tag to T55x7 (or to q5/T5555)`
|`lf pyramid clone `|N |`clone pyramid tag to T55x7 or Q5/T5555`
|`lf pyramid sim `|N |`simulate pyramid tag`
@ -775,27 +869,27 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`lf t55xx help `|Y |`This help`
|`lf t55xx bruteforce `|N |`<start password> <end password> Simple bruteforce attack to find password`
|`lf t55xx config `|Y |`Set/Get T55XX configuration (modulation, inverted, offset, rate)`
|`lf t55xx chk `|N |`Check passwords from dictionary/flash`
|`lf t55xx clonehelp `|N |`Shows the available clone commands`
|`lf t55xx config `|Y |`Set/Get T55XX configuration (modulation, inverted, offset, rate)`
|`lf t55xx dangerraw `|N |`Sends raw bitstream. Dangerous, do not use!! b <bitstream> t <timing>`
|`lf t55xx detect `|Y |`[1] Try detecting the tag modulation from reading the configuration block.`
|`lf t55xx deviceconfig `|N |`Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap`
|`lf t55xx dump `|N |`[password] [o] Dump T55xx card Page 0 block 0-7. Optional [password], [override]`
|`lf t55xx restore `|N |`f <filename> [p <password>] Restore T55xx card Page 0 / Page 1 blocks`
|`lf t55xx info `|Y |`[1] Show T55x7 configuration data (page 0/ blk 0)`
|`lf t55xx p1detect `|N |`[1] Try detecting if this is a t55xx tag by reading page 1`
|`lf t55xx protect `|N |`Password protect tag`
|`lf t55xx read `|N |`b <block> p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]`
|`lf t55xx resetread `|N |`Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)`
|`lf t55xx recoverpw `|N |`[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!`
|`lf t55xx sniff `|N |`Attempt to recover T55xx commands from sample buffer`
|`lf t55xx special `|N |`Show block changes with 64 different offsets`
|`lf t55xx restore `|N |`f <filename> [p <password>] Restore T55xx card Page 0 / Page 1 blocks`
|`lf t55xx trace `|Y |`[1] Show T55x7 traceability data (page 1/ blk 0-1)`
|`lf t55xx wakeup `|N |`Send AOR wakeup command`
|`lf t55xx wipe `|N |`[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)`
|`lf t55xx write `|N |`b <block> d <data> p [password] [1] -- Write T55xx block data. Optional [p password], [page1]`
|`lf t55xx bruteforce `|N |`<start password> <end password> Simple bruteforce attack to find password`
|`lf t55xx chk `|N |`Check passwords from dictionary/flash`
|`lf t55xx protect `|N |`Password protect tag`
|`lf t55xx recoverpw `|N |`[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!`
|`lf t55xx sniff `|Y |`Attempt to recover T55xx commands from sample buffer`
|`lf t55xx special `|N |`Show block changes with 64 different offsets`
|`lf t55xx wipe `|N |`[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)`
### lf viking
@ -807,7 +901,7 @@ Check column "offline" for their availability.
|`lf viking help `|Y |`This help`
|`lf viking demod `|Y |`Demodulate a Viking tag from the GraphBuffer`
|`lf viking read `|N |`Attempt to read and Extract tag data from the antenna`
|`lf viking clone `|N |`clone Viking tag to T55x7 (or to q5/T5555)`
|`lf viking clone `|N |`clone Viking tag to T55x7 or Q5/T5555`
|`lf viking sim `|N |`simulate Viking tag`
@ -820,7 +914,7 @@ Check column "offline" for their availability.
|`lf visa2000 help `|Y |`This help`
|`lf visa2000 demod `|Y |`demodulate an VISA2000 tag from the GraphBuffer`
|`lf visa2000 read `|N |`attempt to read and extract tag data from the antenna`
|`lf visa2000 clone `|N |`clone Visa2000 tag to T55x7 (or to q5/T5555)`
|`lf visa2000 clone `|N |`clone Visa2000 tag to T55x7 or Q5/T5555`
|`lf visa2000 sim `|N |`simulate Visa2000 tag`
@ -831,19 +925,21 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`mem help `|Y |`This help`
|`mem spiffs `|N |`High level SPI FileSystem Flash manipulation [rdv40]`
|`mem spibaud `|N |`Set Flash memory Spi baudrate [rdv40]`
|`mem info `|N |`Flash memory information [rdv40]`
|`mem load `|N |`Load data into flash memory [rdv40]`
|`mem dump `|N |`Dump data from flash memory [rdv40]`
|`mem wipe `|N |`Wipe data from flash memory [rdv40]`
|`mem baudrate `|N |`Set Flash memory Spi baudrate`
|`mem spiffs `|N |`High level SPI FileSystem Flash manipulation`
|`mem info `|N |`Flash memory information`
|`mem load `|N |`Load data into flash memory`
|`mem dump `|N |`Dump data from flash memory`
|`mem wipe `|N |`Wipe data from flash memory`
### reveng
{ CRC calculations from RevEng software }
### sc
[=] reveng: no mode switch specified. Use reveng -h for help.
### smart
{ Smart card ISO-7816 commands... }
@ -865,9 +961,9 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`script help `|Y |`This help`
|`script help `|Y |`Usage info`
|`script list `|Y |`List available scripts`
|`script run `|Y |`<name> -- Execute a script`
|`script run `|Y |`<name> -- execute a script`
### trace
@ -907,7 +1003,7 @@ Check column "offline" for their availability.
|------- |------- |-----------
|`wiegand help `|Y |`This help`
|`wiegand list `|Y |`List available wiegand formats`
|`wiegand encode `|Y |`Convert `
|`wiegand decode `|Y |`Convert raw hex to wiegand format`
|`wiegand encode `|Y |`Encode to wiegand raw hex`
|`wiegand decode `|Y |`Convert raw hex to decoded wiegand format`

BIN
doc/datasheets/hc06.pdf Normal file

Binary file not shown.

Binary file not shown.

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