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
# 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

@ -752,26 +752,26 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
// The soft decision on the bit uses an estimate of just the
// quadrant of the reference angle, not the exact angle.
#define MAKE_SOFT_DECISION() { \
if(Demod.sumI > 0) { \
v = ci; \
} else { \
v = -ci; \
} \
if(Demod.sumQ > 0) { \
v += cq; \
} else { \
v -= cq; \
} \
}
if(Demod.sumI > 0) { \
v = ci; \
} else { \
v = -ci; \
} \
if(Demod.sumQ > 0) { \
v += cq; \
} else { \
v -= cq; \
} \
}
#define SUBCARRIER_DETECT_THRESHOLD 8
#define SUBCARRIER_DETECT_THRESHOLD 8
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
#define AMPLITUDE(ci,cq) (MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2))
switch (Demod.state) {
case DEMOD_UNSYNCD: {
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
Demod.state = DEMOD_PHASE_REF_TRAINING;
Demod.sumI = ci;
Demod.sumQ = cq;
@ -783,7 +783,7 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
// While we get a constant signal
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
if (((ABS(Demod.sumI) > ABS(Demod.sumQ)) && (((ci > 0) && (Demod.sumI > 0)) || ((ci < 0) && (Demod.sumI < 0)))) || // signal closer to horizontal, polarity check based on on I
((ABS(Demod.sumI) <= ABS(Demod.sumQ)) && (((cq > 0) && (Demod.sumQ > 0)) || ((cq < 0) && (Demod.sumQ < 0))))) { // signal closer to vertical, polarity check based on on Q
((ABS(Demod.sumI) <= ABS(Demod.sumQ)) && (((cq > 0) && (Demod.sumQ > 0)) || ((cq < 0) && (Demod.sumQ < 0))))) { // signal closer to vertical, polarity check based on on Q
if (Demod.posCount < 10) { // refine signal approximation during first 10 samples
Demod.sumI += ci;
@ -799,7 +799,7 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
} else {
// at this point it can be start of 14b' data or start of 14b SOF
MAKE_SOFT_DECISION();
Demod.posCount = 1; // this was the first half
Demod.posCount = 1; // this was the first half
Demod.thisBit = v;
Demod.shiftReg = 0;
Demod.state = DEMOD_RECEIVING_DATA;
@ -815,7 +815,7 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
Demod.posCount++;
MAKE_SOFT_DECISION();
if (v > 0) {
if (Demod.posCount > 3 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
if (Demod.posCount > 3 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
LED_C_OFF();
if (Demod.bitCount == 0 && Demod.len == 0) { // received SOF only, this is valid for iClass/Picopass
return true;
@ -823,8 +823,8 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
Demod.state = DEMOD_UNSYNCD;
}
}
} else { // start bit detected
Demod.posCount = 1; // this was the first half
} else { // start bit detected
Demod.posCount = 1; // this was the first half
Demod.thisBit = v;
Demod.shiftReg = 0;
Demod.state = DEMOD_RECEIVING_DATA;
@ -857,14 +857,14 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
MAKE_SOFT_DECISION();
if (Demod.posCount == 0) { // first half of bit
if (Demod.posCount == 0) { // first half of bit
Demod.thisBit = v;
Demod.posCount = 1;
} else { // second half of bit
} else { // second half of bit
Demod.thisBit += v;
Demod.shiftReg >>= 1;
if (Demod.thisBit > 0) { // logic '1'
if (Demod.thisBit > 0) { // logic '1'
Demod.shiftReg |= 0x200;
}
@ -996,7 +996,7 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
if (Handle14443bSamplesFromTag(ci, cq)) {
*eof_time = dma_start_time + (samples ) - DELAY_TAG_TO_ARM; // end of EOF
*eof_time = dma_start_time + (samples) - DELAY_TAG_TO_ARM; // end of EOF
if (Demod.len > Demod.max_len) {
ret = -2; // overflow
@ -1854,7 +1854,7 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
int status;
uint32_t sendlen = sizeof(iso14b_card_select_t);
iso14b_card_select_t card;
memset((void*)&card, 0x00, sizeof(card));
memset((void *)&card, 0x00, sizeof(card));
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
status = iso14443b_select_card(&card);

View file

@ -1883,112 +1883,112 @@ void LockPassSlixIso15693(uint32_t pass_id, uint32_t password) {
LED_A_ON();
uint8_t cmd_inventory[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1, 0x01, 0x00, 0x00, 0x00 };
uint8_t cmd_get_rnd[] = {ISO15693_REQ_DATARATE_HIGH, 0xB2, 0x04, 0x00, 0x00 };
uint8_t cmd_set_pass[] = {ISO15693_REQ_DATARATE_HIGH, 0xB3, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//uint8_t cmd_write_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, 0xB4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t cmd_lock_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, 0xB5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 };
uint16_t crc;
int recvlen = 0;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint32_t start_time = 0;
bool done = false;
uint8_t cmd_inventory[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1, 0x01, 0x00, 0x00, 0x00 };
uint8_t cmd_get_rnd[] = {ISO15693_REQ_DATARATE_HIGH, 0xB2, 0x04, 0x00, 0x00 };
uint8_t cmd_set_pass[] = {ISO15693_REQ_DATARATE_HIGH, 0xB3, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//uint8_t cmd_write_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, 0xB4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t cmd_lock_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, 0xB5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 };
uint16_t crc;
int recvlen = 0;
uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
uint32_t start_time = 0;
bool done = false;
// setup 'get random number' command
crc = Iso15693Crc(cmd_get_rnd, 3);
cmd_get_rnd[3] = crc & 0xff;
cmd_get_rnd[4] = crc >> 8;
// setup 'get random number' command
crc = Iso15693Crc(cmd_get_rnd, 3);
cmd_get_rnd[3] = crc & 0xff;
cmd_get_rnd[4] = crc >> 8;
Dbprintf("LockPass: Press button lock password, long-press to terminate.");
Dbprintf("LockPass: Press button lock password, long-press to terminate.");
while (!done) {
while (!done) {
LED_D_ON();
switch(BUTTON_HELD(1000)) {
case BUTTON_SINGLE_CLICK:
Dbprintf("LockPass: Reset 'DONE'-LED (A)");
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
break;
case BUTTON_HOLD:
Dbprintf("LockPass: Terminating");
done = true;
break;
default:
SpinDelay(50);
continue;
}
LED_D_ON();
switch(BUTTON_HELD(1000)) {
case BUTTON_SINGLE_CLICK:
Dbprintf("LockPass: Reset 'DONE'-LED (A)");
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
break;
case BUTTON_HOLD:
Dbprintf("LockPass: Terminating");
done = true;
break;
default:
SpinDelay(50);
continue;
}
if (done) [
break;
}
if (done) [
break;
}
recvlen = SendDataTag(cmd_get_rnd, sizeof(cmd_get_rnd), true, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 5) {
LED_C_ON();
} else {
Dbprintf("LockPass: Received random 0x%02X%02X (%d)", recvbuf[1], recvbuf[2], recvlen);
recvlen = SendDataTag(cmd_get_rnd, sizeof(cmd_get_rnd), true, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 5) {
LED_C_ON();
} else {
Dbprintf("LockPass: Received random 0x%02X%02X (%d)", recvbuf[1], recvbuf[2], recvlen);
// setup 'set password' command
cmd_set_pass[4] = ((password>>0) &0xFF) ^ recvbuf[1];
cmd_set_pass[5] = ((password>>8) &0xFF) ^ recvbuf[2];
cmd_set_pass[6] = ((password>>16) &0xFF) ^ recvbuf[1];
cmd_set_pass[7] = ((password>>24) &0xFF) ^ recvbuf[2];
// setup 'set password' command
cmd_set_pass[4] = ((password>>0) &0xFF) ^ recvbuf[1];
cmd_set_pass[5] = ((password>>8) &0xFF) ^ recvbuf[2];
cmd_set_pass[6] = ((password>>16) &0xFF) ^ recvbuf[1];
cmd_set_pass[7] = ((password>>24) &0xFF) ^ recvbuf[2];
crc = Iso15693Crc(cmd_set_pass, 8);
cmd_set_pass[8] = crc & 0xff;
cmd_set_pass[9] = crc >> 8;
crc = Iso15693Crc(cmd_set_pass, 8);
cmd_set_pass[8] = crc & 0xff;
cmd_set_pass[9] = crc >> 8;
Dbprintf("LockPass: Sending old password to end privacy mode", cmd_set_pass[4], cmd_set_pass[5], cmd_set_pass[6], cmd_set_pass[7]);
recvlen = SendDataTag(cmd_set_pass, sizeof(cmd_set_pass), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 3) {
Dbprintf("LockPass: Failed to set password (%d)", recvlen);
LED_B_ON();
} else {
crc = Iso15693Crc(cmd_inventory, 3);
cmd_inventory[3] = crc & 0xff;
cmd_inventory[4] = crc >> 8;
Dbprintf("LockPass: Sending old password to end privacy mode", cmd_set_pass[4], cmd_set_pass[5], cmd_set_pass[6], cmd_set_pass[7]);
recvlen = SendDataTag(cmd_set_pass, sizeof(cmd_set_pass), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 3) {
Dbprintf("LockPass: Failed to set password (%d)", recvlen);
LED_B_ON();
} else {
crc = Iso15693Crc(cmd_inventory, 3);
cmd_inventory[3] = crc & 0xff;
cmd_inventory[4] = crc >> 8;
Dbprintf("LockPass: Searching for tag...");
recvlen = SendDataTag(cmd_inventory, sizeof(cmd_inventory), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 12) {
Dbprintf("LockPass: Failed to read inventory (%d)", recvlen);
LED_B_ON();
LED_C_ON();
} else {
Dbprintf("LockPass: Searching for tag...");
recvlen = SendDataTag(cmd_inventory, sizeof(cmd_inventory), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 12) {
Dbprintf("LockPass: Failed to read inventory (%d)", recvlen);
LED_B_ON();
LED_C_ON();
} else {
Dbprintf("LockPass: Answer from %02X%02X%02X%02X%02X%02X%02X%02X", recvbuf[9], recvbuf[8], recvbuf[7], recvbuf[6], recvbuf[5], recvbuf[4], recvbuf[3], recvbuf[2]);
Dbprintf("LockPass: Answer from %02X%02X%02X%02X%02X%02X%02X%02X", recvbuf[9], recvbuf[8], recvbuf[7], recvbuf[6], recvbuf[5], recvbuf[4], recvbuf[3], recvbuf[2]);
memcpy(&cmd_lock_pass[3], &recvbuf[2], 8);
memcpy(&cmd_lock_pass[3], &recvbuf[2], 8);
cmd_lock_pass[8+3] = pass_id;
cmd_lock_pass[8+3] = pass_id;
crc = Iso15693Crc(cmd_lock_pass, 8+4);
cmd_lock_pass[8+4] = crc & 0xff;
cmd_lock_pass[8+5] = crc >> 8;
crc = Iso15693Crc(cmd_lock_pass, 8+4);
cmd_lock_pass[8+4] = crc & 0xff;
cmd_lock_pass[8+5] = crc >> 8;
Dbprintf("LockPass: locking to password 0x%02X%02X%02X%02X for ID %02X", cmd_set_pass[4], cmd_set_pass[5], cmd_set_pass[6], cmd_set_pass[7], pass_id);
Dbprintf("LockPass: locking to password 0x%02X%02X%02X%02X for ID %02X", cmd_set_pass[4], cmd_set_pass[5], cmd_set_pass[6], cmd_set_pass[7], pass_id);
recvlen = SendDataTag(cmd_lock_pass, sizeof(cmd_lock_pass), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 3) {
Dbprintf("LockPass: Failed to lock password (%d)", recvlen);
} else {
Dbprintf("LockPass: Successful (%d)", recvlen);
}
LED_A_ON();
}
} }
}
recvlen = SendDataTag(cmd_lock_pass, sizeof(cmd_lock_pass), false, true, recvbuf, sizeof(recvbuf), start_time);
if (recvlen != 3) {
Dbprintf("LockPass: Failed to lock password (%d)", recvlen);
} else {
Dbprintf("LockPass: Successful (%d)", recvlen);
}
LED_A_ON();
}
} }
}
Dbprintf("LockPass: Finishing");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
Dbprintf("LockPass: Finishing");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
cmd_send(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
cmd_send(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen);
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
}
*/

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);
// Wait 20ms for write to complete?
WaitMS(7);
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?
// 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();
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);
reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0);
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

@ -2231,9 +2231,9 @@ struct arg_int *arg_intn(
#include <limits.h>
#include <inttypes.h>
static uint64_t strtollu0X(const char *str,
const char * *endptr,
char X,
int base) {
const char * *endptr,
char X,
int base) {
uint64_t val; /* stores result */
int s = 1; /* sign is +1 or -1 */
const char *ptr = str; /* ptr to current position in str */
@ -4529,11 +4529,11 @@ static void arg_cat_optionv(char *dest,
}
if (datatype) {
/* if (longopts)
arg_cat(&dest, "=", &ndest);
else if (shortopts)
arg_cat(&dest, " ", &ndest);
*/
/* if (longopts)
arg_cat(&dest, "=", &ndest);
else if (shortopts)
arg_cat(&dest, " ", &ndest);
*/
if (longopts)
arg_cat(&dest, " ", &ndest);
else if (shortopts)

View file

@ -192,19 +192,19 @@ struct arg_int *arg_int1(const char *shortopts, const char *longopts, const char
struct arg_int *arg_intn(const char *shortopts, const char *longopts, const char *datatype, int mincount, int maxcount, const char *glossary);
struct arg_u64 *arg_u64_0(const char *shortopts,
const char *longopts,
const char *datatype,
const char *glossary);
const char *longopts,
const char *datatype,
const char *glossary);
struct arg_u64 *arg_u64_1(const char *shortopts,
const char *longopts,
const char *datatype,
const char *glossary);
const char *longopts,
const char *datatype,
const char *glossary);
struct arg_u64 *arg_u64_n(const char *shortopts,
const char *longopts,
const char *datatype,
int mincount,
int maxcount,
const char *glossary);
const char *longopts,
const char *datatype,
int mincount,
int maxcount,
const char *glossary);
struct arg_dbl *arg_dbl0(const char *shortopts,

View file

@ -174,7 +174,7 @@ crack_states_thread(void *x) {
char progress_text[80];
char keystr[19];
sprintf(keystr, "%012" PRIx64 " ", key);
sprintf(progress_text, "Brute force phase completed. Key found: " _YELLOW_("%s"), keystr);
sprintf(progress_text, "Brute force phase completed. Key found: " _YELLOW_("%s"), keystr);
hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0);
break;
} else if (keys_found) {

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,16 +427,20 @@ 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) {
@ -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

@ -77,65 +77,65 @@ local function setdevicedebug( status )
end
local function xteaCrypt(num_rounds, v, key)
local v0 = v[0]
local v1 = v[1]
local delta = 0x9E3779B9
local sum = 0
local v0 = v[0]
local v1 = v[1]
local delta = 0x9E3779B9
local sum = 0
for i = 0, num_rounds-1 do
-- v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
v0 = band(bxor(bxor(lsh(v1,4), rsh(v1,5)) + v1, sum + key[band(sum,3)]) + v0, 0xFFFFFFFF)
sum = band(sum + delta, 0xFFFFFFFF)
-- v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
v1 = band(bxor(bxor(lsh(v0,4), rsh(v0,5)) + v0, sum + key[band(rsh(sum,11),3)]) + v1, 0xFFFFFFFF)
end
v[0] = v0
v[1] = v1
for i = 0, num_rounds-1 do
-- v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
v0 = band(bxor(bxor(lsh(v1,4), rsh(v1,5)) + v1, sum + key[band(sum,3)]) + v0, 0xFFFFFFFF)
sum = band(sum + delta, 0xFFFFFFFF)
-- v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
v1 = band(bxor(bxor(lsh(v0,4), rsh(v0,5)) + v0, sum + key[band(rsh(sum,11),3)]) + v1, 0xFFFFFFFF)
end
v[0] = v0
v[1] = v1
end
local function xteaDecrypt(num_rounds, v, key)
local v0 = v[0]
local v1 = v[1]
local delta = 0x9E3779B9
local sum = band(delta * num_rounds, 0xFFFFFFFF)
local v0 = v[0]
local v1 = v[1]
local delta = 0x9E3779B9
local sum = band(delta * num_rounds, 0xFFFFFFFF)
for i = 0, num_rounds-1 do
-- v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
v1 = band(v1 - bxor(bxor(lsh(v0,4), rsh(v0,5)) + v0, sum + key[band(rsh(sum,11),3)]), 0xFFFFFFFF)
sum = band(sum - delta, 0xFFFFFFFF)
-- v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
v0 = band(v0 - bxor(bxor(lsh(v1,4), rsh(v1,5)) + v1, sum + key[band(sum,3)]), 0xFFFFFFFF)
end
v[0] = v0
v[1] = v1
for i = 0, num_rounds-1 do
-- v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
v1 = band(v1 - bxor(bxor(lsh(v0,4), rsh(v0,5)) + v0, sum + key[band(rsh(sum,11),3)]), 0xFFFFFFFF)
sum = band(sum - delta, 0xFFFFFFFF)
-- v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
v0 = band(v0 - bxor(bxor(lsh(v1,4), rsh(v1,5)) + v1, sum + key[band(sum,3)]), 0xFFFFFFFF)
end
v[0] = v0
v[1] = v1
end
local function createxteakey(mfuid)
local xteakey = {}
local buid = {}
local tmpkey = {}
local uid = {}
local xteakey = {}
local buid = {}
local tmpkey = {}
local uid = {}
-- Warning ! "it is customary in Lua to START ARRAYS WITH ONE"
buid = utils.ConvertHexToBytes(mfuid)
uid[0] = bor(buid[1], lsh(buid[2], 8))
uid[1] = bor(buid[3], lsh(buid[4], 8))
-- Warning ! "it is customary in Lua to START ARRAYS WITH ONE"
buid = utils.ConvertHexToBytes(mfuid)
uid[0] = bor(buid[1], lsh(buid[2], 8))
uid[1] = bor(buid[3], lsh(buid[4], 8))
tmpkey[0] = 0x198B
tmpkey[1] = uid[0]
tmpkey[2] = 0x46D8
tmpkey[3] = uid[1]
tmpkey[4] = 0x5310
tmpkey[5] = bxor(uid[0], 0xA312)
tmpkey[6] = 0xFFCB
tmpkey[7] = bxor(uid[1], 0x55AA)
tmpkey[0] = 0x198B
tmpkey[1] = uid[0]
tmpkey[2] = 0x46D8
tmpkey[3] = uid[1]
tmpkey[4] = 0x5310
tmpkey[5] = bxor(uid[0], 0xA312)
tmpkey[6] = 0xFFCB
tmpkey[7] = bxor(uid[1], 0x55AA)
xteakey[0] = bor(lsh(tmpkey[1], 16), tmpkey[0])
xteakey[1] = bor(lsh(tmpkey[3], 16), tmpkey[2])
xteakey[2] = bor(lsh(tmpkey[5], 16), tmpkey[4])
xteakey[3] = bor(lsh(tmpkey[7], 16), tmpkey[6])
xteakey[0] = bor(lsh(tmpkey[1], 16), tmpkey[0])
xteakey[1] = bor(lsh(tmpkey[3], 16), tmpkey[2])
xteakey[2] = bor(lsh(tmpkey[5], 16), tmpkey[4])
xteakey[3] = bor(lsh(tmpkey[7], 16), tmpkey[6])
return xteakey
return xteakey
end
local function getblockdata(response)
@ -160,38 +160,38 @@ local function readblock(blockno, key)
end
local function readtag(mfkey,xteakey)
local tagdata = {}
local cleardata = {}
local v = {}
local vv = {}
local tagdata = {}
local cleardata = {}
local v = {}
local vv = {}
-- Read 4 sectors and build table
for sect = 8, 11 do
for blockn = sect * 4, (sect * 4) + 2 do
local blockdata = readblock(blockn, mfkey)
if not blockdata then return oops('[!] failed reading block') end
table.insert(tagdata, blockdata)
end
end
-- Read 4 sectors and build table
for sect = 8, 11 do
for blockn = sect * 4, (sect * 4) + 2 do
local blockdata = readblock(blockn, mfkey)
if not blockdata then return oops('[!] failed reading block') end
table.insert(tagdata, blockdata)
end
end
-- Decrypt data and build clear table
for key,value in ipairs(tagdata) do
local clearblockdata
v[0] = utils.SwapEndianness(value:sub(1, 8), 32)
v[1] = utils.SwapEndianness(value:sub(9, 16), 32)
xteaDecrypt(16, v, xteakey)
vv[0] = utils.SwapEndianness(value:sub(17, 24), 32)
vv[1] = utils.SwapEndianness(value:sub(25, 32), 32)
xteaDecrypt(16, vv, xteakey)
clearblockdata=string.format("%08X%08X%08X%08X",
utils.SwapEndianness(string.format("%08X", v[0]), 32),
utils.SwapEndianness(string.format("%08X", v[1]), 32),
utils.SwapEndianness(string.format("%08X", vv[0]), 32),
utils.SwapEndianness(string.format("%08X", vv[1]), 32))
table.insert(cleardata, clearblockdata)
end
-- Decrypt data and build clear table
for key,value in ipairs(tagdata) do
local clearblockdata
v[0] = utils.SwapEndianness(value:sub(1, 8), 32)
v[1] = utils.SwapEndianness(value:sub(9, 16), 32)
xteaDecrypt(16, v, xteakey)
vv[0] = utils.SwapEndianness(value:sub(17, 24), 32)
vv[1] = utils.SwapEndianness(value:sub(25, 32), 32)
xteaDecrypt(16, vv, xteakey)
clearblockdata=string.format("%08X%08X%08X%08X",
utils.SwapEndianness(string.format("%08X", v[0]), 32),
utils.SwapEndianness(string.format("%08X", v[1]), 32),
utils.SwapEndianness(string.format("%08X", vv[0]), 32),
utils.SwapEndianness(string.format("%08X", vv[1]), 32))
table.insert(cleardata, clearblockdata)
end
return tagdata,cleardata
return tagdata,cleardata
end
@ -203,98 +203,98 @@ local function main(args)
if o == 'h' then return help() end
end
local xteakey = {}
-- local v = {}
local edata = {}
local cdata = {}
local xteakey = {}
-- local v = {}
local edata = {}
local cdata = {}
-- Turn off Debug
setdevicedebug(false)
-- Turn off Debug
setdevicedebug(false)
-- GET TAG UID
tag, err = lib14a.read(false, true)
if err then
lib14a.disconnect()
return oops(err)
end
core.clearCommandBuffer()
-- GET TAG UID
tag, err = lib14a.read(false, true)
if err then
lib14a.disconnect()
return oops(err)
end
core.clearCommandBuffer()
-- simple tag check
if 0x08 ~= tag.sak then
if 0x0400 ~= tag.atqa then
return oops(('[fail] found tag %s :: looking for Mifare S50 1k'):format(tag.name))
end
end
-- simple tag check
if 0x08 ~= tag.sak then
if 0x0400 ~= tag.atqa then
return oops(('[fail] found tag %s :: looking for Mifare S50 1k'):format(tag.name))
end
end
xteakey = createxteakey(tag.uid)
print(acblue.."UID: "..tag.uid..acoff)
print(acblue..string.format("XTEA key: %08X %08X %08X %08X", xteakey[0], xteakey[1], xteakey[2], xteakey[3])..acoff)
xteakey = createxteakey(tag.uid)
print(acblue.."UID: "..tag.uid..acoff)
print(acblue..string.format("XTEA key: %08X %08X %08X %08X", xteakey[0], xteakey[1], xteakey[2], xteakey[3])..acoff)
edata, cdata = readtag("415A54454B4D", xteakey)
edata, cdata = readtag("415A54454B4D", xteakey)
if edata == nil or cdata == nil then
print("ERROR Reading tag!")
return nil
end
if edata == nil or cdata == nil then
print("ERROR Reading tag!")
return nil
end
print("Ciphered data:")
for key,value in ipairs(edata) do
print(value)
if key % 3 == 0 then print("") end
end
print("Ciphered data:")
for key,value in ipairs(edata) do
print(value)
if key % 3 == 0 then print("") end
end
-- compute CRC for each segment
-- compute CRC for each segment
crcH = utils.SwapEndianness(core.reveng_runmodel("CRC-16/ARC", cdata[1]..cdata[2]..cdata[3]:sub(1,28), false, '0'),16)
crcA = utils.SwapEndianness(core.reveng_runmodel("CRC-16/ARC", cdata[4]..cdata[5]..cdata[6]..cdata[7]:sub(1,28), false, '0'),16)
crcB = utils.SwapEndianness(core.reveng_runmodel("CRC-16/ARC", cdata[8]..cdata[9]..cdata[10]..cdata[11]:sub(1,28), false, '0'),16)
print("\nHeader:")
for key,value in ipairs(cdata) do
if key == 3 then
print(value:sub(1,28)..acmagenta..value:sub(29,32)..acoff)
if utils.SwapEndianness(value:sub(29,32),16) == crcH then strcrc = " OK" else strcrc = acred.." CRCERROR !!" end
print(acmagenta.."CRC16/ARC = "..string.format("0x%04X", crcH)..strcrc..acoff)
print("\nDataA:")
elseif key == 4 then
print(acgreen..value:sub(1,4)..acoff..value:sub(5,16)..accyan..value:sub(17,24)..acoff..value:sub(25,26)..accyan..value:sub(27,28)..acoff..value:sub(29,32))
versionA = utils.SwapEndianness(value:sub(1,4),16)
dateA = string.format("%d/%02d/%02d %02d:%02d", tonumber(value:sub(17,18),10)+2000, tonumber(value:sub(19,20),10),
tonumber(string.format("%02X", band(tonumber(value:sub(21,22),16),0x3f)),10),
tonumber(value:sub(23,24),10), tonumber(value:sub(27,28),10))
elseif key == 8 then
print(acgreen..value:sub(1,4)..acoff..value:sub(5,16)..accyan..value:sub(17,24)..acoff..value:sub(25,26)..accyan..value:sub(27,28)..acoff..value:sub(29,32))
versionB = utils.SwapEndianness(value:sub(1,4),16)
dateB = string.format("%d/%02d/%02d %02d:%02d", tonumber(value:sub(17,18),10)+2000, tonumber(value:sub(19,20),10),
tonumber(string.format("%02X", band(tonumber(value:sub(21,22),16),0x3f)),10),
tonumber(value:sub(23,24),10), tonumber(value:sub(27,28),10))
elseif key == 5 then
print(acyellow..value:sub(1,4)..acoff..value:sub(5,32))
creditA = utils.SwapEndianness(value:sub(1,4),16)/100
elseif key == 9 then
print(acyellow..value:sub(1,4)..acoff..value:sub(5,32))
creditB = utils.SwapEndianness(value:sub(1,4),16)/100
elseif key == 7 then
print(value:sub(1,28)..acmagenta..value:sub(29,32)..acoff)
print(acgreen.."Version "..string.format("0x%04X", versionA)..acoff)
print(acyellow.."Credit : "..creditA..acoff)
if utils.SwapEndianness(value:sub(29,32),16) == crcA then strcrc = " OK" else strcrc = acred.." CRCERROR !!" end
print(acmagenta.."CRC16/ARC = "..string.format("0x%04X", crcA)..strcrc..acoff)
print(accyan.."Date: "..dateA..acoff)
print("\nDataB:")
elseif key == 11 then
print(value:sub(1,28)..acmagenta..value:sub(29,32)..acoff)
print(acgreen.."Version "..string.format("0x%04X", versionB)..acoff)
print(acyellow.."Credit : "..creditB..acoff)
if utils.SwapEndianness(value:sub(29,32),16) == crcB then strcrc = " OK" else strcrc = acred.." CRCERROR !!" end
print(acmagenta.."CRC16/ARC = "..string.format("0x%04X", crcB)..strcrc..acoff)
print(accyan.."Date: "..dateB..acoff)
print("\nFooter:")
else
print(value)
end
end
print("\nHeader:")
for key,value in ipairs(cdata) do
if key == 3 then
print(value:sub(1,28)..acmagenta..value:sub(29,32)..acoff)
if utils.SwapEndianness(value:sub(29,32),16) == crcH then strcrc = " OK" else strcrc = acred.." CRCERROR !!" end
print(acmagenta.."CRC16/ARC = "..string.format("0x%04X", crcH)..strcrc..acoff)
print("\nDataA:")
elseif key == 4 then
print(acgreen..value:sub(1,4)..acoff..value:sub(5,16)..accyan..value:sub(17,24)..acoff..value:sub(25,26)..accyan..value:sub(27,28)..acoff..value:sub(29,32))
versionA = utils.SwapEndianness(value:sub(1,4),16)
dateA = string.format("%d/%02d/%02d %02d:%02d", tonumber(value:sub(17,18),10)+2000, tonumber(value:sub(19,20),10),
tonumber(string.format("%02X", band(tonumber(value:sub(21,22),16),0x3f)),10),
tonumber(value:sub(23,24),10), tonumber(value:sub(27,28),10))
elseif key == 8 then
print(acgreen..value:sub(1,4)..acoff..value:sub(5,16)..accyan..value:sub(17,24)..acoff..value:sub(25,26)..accyan..value:sub(27,28)..acoff..value:sub(29,32))
versionB = utils.SwapEndianness(value:sub(1,4),16)
dateB = string.format("%d/%02d/%02d %02d:%02d", tonumber(value:sub(17,18),10)+2000, tonumber(value:sub(19,20),10),
tonumber(string.format("%02X", band(tonumber(value:sub(21,22),16),0x3f)),10),
tonumber(value:sub(23,24),10), tonumber(value:sub(27,28),10))
elseif key == 5 then
print(acyellow..value:sub(1,4)..acoff..value:sub(5,32))
creditA = utils.SwapEndianness(value:sub(1,4),16)/100
elseif key == 9 then
print(acyellow..value:sub(1,4)..acoff..value:sub(5,32))
creditB = utils.SwapEndianness(value:sub(1,4),16)/100
elseif key == 7 then
print(value:sub(1,28)..acmagenta..value:sub(29,32)..acoff)
print(acgreen.."Version "..string.format("0x%04X", versionA)..acoff)
print(acyellow.."Credit : "..creditA..acoff)
if utils.SwapEndianness(value:sub(29,32),16) == crcA then strcrc = " OK" else strcrc = acred.." CRCERROR !!" end
print(acmagenta.."CRC16/ARC = "..string.format("0x%04X", crcA)..strcrc..acoff)
print(accyan.."Date: "..dateA..acoff)
print("\nDataB:")
elseif key == 11 then
print(value:sub(1,28)..acmagenta..value:sub(29,32)..acoff)
print(acgreen.."Version "..string.format("0x%04X", versionB)..acoff)
print(acyellow.."Credit : "..creditB..acoff)
if utils.SwapEndianness(value:sub(29,32),16) == crcB then strcrc = " OK" else strcrc = acred.." CRCERROR !!" end
print(acmagenta.."CRC16/ARC = "..string.format("0x%04X", crcB)..strcrc..acoff)
print(accyan.."Date: "..dateB..acoff)
print("\nFooter:")
else
print(value)
end
end
return
return
end
main(args)

View file

@ -34,7 +34,7 @@ version = 'v1.0.0'
desc = [[
This script gives you an easy way to write your *.eml dumps into normal MIFARE Classic and Magic Gen3 cards.
Works with both 4 and 7 bytes NXP MIFARE Classic 1K cards.
Works with both 4 and 7 bytes NXP MIFARE Classic 1K cards.
The script also has the possibility to change UID and permanent lock uid on magic Gen3 cards.
It supports the following functionality.
@ -47,18 +47,18 @@ desc = [[
Script works in a wizard styled way.
Author Youtube channel: https://yev.ooo/
Author Youtube channel: https://yev.ooo/
Many Thanks,
Best Regards
Many Thanks,
Best Regards
]]
example = [[
1. script run mfc_gen3_writer
]]
usage = [[
Give script to know if you uses an Windows OS
Give script to know if you uses an Windows OS
Select your *.eml dump from list to write to the card.
Follow the wizard.
Follow the wizard.
]]
--
---
@ -163,9 +163,9 @@ end
--
local function KeyAB()
if default_key_type == '00' then
return 'KeyA'
return 'KeyA'
else
return 'KeyB'
return 'KeyB'
end
end
--
@ -265,7 +265,7 @@ local function main(args)
eml_file_uid_end = 22
eml_file_lengt = 31
else
eml_file_uid_start = 9
eml_file_uid_start = 9
eml_file_uid_end = 16
eml_file_lengt = 25
end
@ -366,7 +366,7 @@ local function main(args)
print(tab)
--
if checkkey() == true then
print(tab)
print(tab)
if (utils.confirm(' Card is Empty. Write selected dump to card ?') == true) then
for i = 1, #eml do
core.console(string.format(cmd_wrbl_b, (i-1), default_key, eml[i]))

View file

@ -114,7 +114,7 @@ local function main(args)
local c = string.format( command, n )
print('Running: "'..c..'"')
core.console(c)
core.console('msleep '..timeout);
core.console('msleep '..timeout);
core.console('hw ping')
end

File diff suppressed because it is too large Load diff

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 (Cmd[0] == 's') {
st = true;
Cmd++;
} else if (Cmd[1] == 's') {
st = true;
Cmd += 2;
}
int clk = 0;
int invert = 0;
int maxErr = 100;
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;
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';
if (slen) {
if (Cmd[0] == 's') {
st = true;
Cmd++;
} else if (slen > 1 && Cmd[1] == 's') {
st = true;
Cmd += 2;
}
char amp = tolower(param_getchar(Cmd, 0));
sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &amp);
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,32 +1967,32 @@ 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;
CursorScaleFactorUnit[0] = '\x00';
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t*)CursorScaleFactorUnit, sizeof(CursorScaleFactorUnit), &len);
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)CursorScaleFactorUnit, sizeof(CursorScaleFactorUnit), &len);
CLIParserFree(ctx);
RepaintGraphWindow();
return PM3_SUCCESS;
@ -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"},
{"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"},
{"hide", CmdHide, AlwaysAvailable, "Hide graph window"},
{"hpf", CmdHpf, AlwaysAvailable, "Remove DC offset from trace"},
{"load", CmdLoad, AlwaysAvailable, "<filename> -- Load trace (to graph window"},
{"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)"},
{"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"},
{"zerocrossings", CmdZerocrossings, AlwaysAvailable, "Count time between zero-crossings"},
{"iir", CmdDataIIR, AlwaysAvailable, "apply IIR buttersworth filter on plotdata"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"-----------", 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)"},
{"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"},
{"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"},
{"mtrim", CmdMtrim, AlwaysAvailable, "<start> <stop> -- Trim out samples from the specified start to the specified stop"},
{"norm", CmdNorm, AlwaysAvailable, "Normalize max/min to +/-128"},
{"plot", CmdPlot, AlwaysAvailable, "Show graph window (hit 'h' in window for keystroke help)"},
{"rtrim", CmdRtrim, AlwaysAvailable, "<location to end trace> -- Trim samples from right of trace"},
{"setgraphmarkers", CmdSetGraphMarkers, AlwaysAvailable, "[orange_marker] [blue_marker] (in graph window)"},
{"shiftgraphzero", CmdGraphShiftZero, AlwaysAvailable, "<shift> -- Shift 0 for Graphed wave + or - shift value"},
{"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"},
{"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

@ -35,7 +35,7 @@ static int CmdFlashmemSpiBaudrate(const char *Cmd) {
"Unless you know what you are doing, please stay at 24MHz.\n"
"If >= 24MHz, FASTREADS instead of READS instruction will be used.",
"mem baudrate --mhz 48"
);
);
void *argtable[] = {
arg_param_begin,
@ -72,7 +72,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
"mem load -f mfc_default_keys -m -> upload MFC keys\n"
"mem load -f t55xx_default_pwds -t -> upload T55XX passwords\n"
"mem load -f iclass_default_keys -i -> upload iCLASS keys\n"
);
);
void *argtable[] = {
arg_param_begin,
@ -91,7 +91,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
bool is_t55xx = arg_get_lit(ctx, 4);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
Dictionary_t d = DICTIONARY_NONE;
@ -227,7 +227,7 @@ static int CmdFlashMemDump(const char *Cmd) {
"mem dump -f myfile -> download all flashmem to file\n"
"mem dump --view -o 262015 --len 128 -> display 128 bytes from offset 262015 (RSA sig)\n"
"mem dump --view -f myfile -o 241664 --len 58 -> display 58 bytes from offset 241664 and save to file"
);
);
void *argtable[] = {
arg_param_begin,
@ -244,7 +244,7 @@ static int CmdFlashMemDump(const char *Cmd) {
bool view = arg_get_lit(ctx, 3);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
uint8_t *dump = calloc(len, sizeof(uint8_t));
@ -282,7 +282,7 @@ static int CmdFlashMemWipe(const char *Cmd) {
_WHITE_("[ ") _RED_("!!! OBS") " ] use with caution",
"mem wipe -p 0 -> wipes first page"
// "mem wipe -i -> inital total wipe"
);
);
void *argtable[] = {
arg_param_begin,
@ -297,7 +297,7 @@ static int CmdFlashMemWipe(const char *Cmd) {
// initalwipe = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
if (page < 0 || page > 2 ) {
if (page < 0 || page > 2) {
PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
return PM3_EINVARG;
}
@ -310,7 +310,7 @@ static int CmdFlashMemWipe(const char *Cmd) {
return PM3_ETIMEOUT;
}
const char* msg = "Flash WIPE ";
const char *msg = "Flash WIPE ";
uint8_t isok = resp.oldarg[0] & 0xFF;
if (isok)
PrintAndLogEx(SUCCESS, "%s ( " _GREEN_("ok")" )", msg);
@ -329,7 +329,7 @@ static int CmdFlashMemInfo(const char *Cmd) {
"Collect signature and verify it from flash memory",
"mem info"
// "mem info -s"
);
);
void *argtable[] = {
arg_param_begin,
@ -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) {
@ -127,7 +132,7 @@ static int CmdHF14BSim(const char *Cmd) {
"Simulate a ISO/IEC 14443 type B tag with 4 byte UID / PUPI",
"hf 14b sim\n"
"hf 14b sim -u 11AA33BB"
);
);
void *argtable[] = {
arg_param_begin,
@ -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;
@ -155,7 +161,7 @@ static int CmdHF14BSniff(const char *Cmd) {
CLIParserInit(&ctx, "hf 14b sniff",
"Sniff the communication reader and tag",
"hf 14b sniff"
);
);
void *argtable[] = {
arg_param_begin,
@ -183,16 +189,16 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
"hf 14b raw -cks --data 0200a40400 -> standard select\n"
"hf 14b raw -ck --sr --data 0200a40400 -> SRx select\n"
"hf 14b raw -ck --cts --data 0200a40400 -> C-ticket select\n"
);
);
void *argtable[] = {
arg_param_begin,
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
arg_lit0("s", "std", "activate field and select standard card"),
arg_lit0(NULL, "sr", "activate field and select SRx ST"),
arg_lit0(NULL, "cts", "activate field and select ASK C-ticket"),
arg_lit0("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);
@ -618,7 +625,7 @@ static void print_ct_general_info(void *vcard) {
iso14b_cts_card_select_t card;
memcpy(&card, (iso14b_cts_card_select_t *)vcard, sizeof(iso14b_cts_card_select_t));
uint32_t uid32 = (card.uid[0] |card.uid[1] << 8 |card.uid[2] << 16 | card.uid[3] << 24);
uint32_t uid32 = (card.uid[0] | card.uid[1] << 8 | card.uid[2] << 16 | card.uid[3] << 24);
PrintAndLogEx(SUCCESS, "ASK C-Ticket");
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s") " ( " _YELLOW_("%010u") " )", sprint_hex(card.uid, sizeof(card.uid)), uid32);
PrintAndLogEx(SUCCESS, " Product Code: %02X", card.pc);
@ -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;
}
@ -711,7 +718,7 @@ static int CmdHF14Binfo(const char *Cmd) {
CLIParserInit(&ctx, "hf 14b info",
"Tag information for ISO/IEC 14443 type B based tags",
"hf 14b info\n"
);
);
void *argtable[] = {
arg_param_begin,
@ -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;
}
@ -937,7 +944,7 @@ static int CmdHF14BReader(const char *Cmd) {
CLIParserInit(&ctx, "hf 14b reader",
"Act as a 14443B reader to identify a tag",
"hf 14b reader\n"
);
);
void *argtable[] = {
arg_param_begin,
@ -960,7 +967,7 @@ static int CmdHF14BReadSri(const char *Cmd) {
CLIParserInit(&ctx, "hf 14b sriread",
"Read contents of a SRI512 | SRIX4K tag",
"hf 14b sriread\n"
);
);
void *argtable[] = {
arg_param_begin,
@ -1068,7 +1075,7 @@ static int CmdHF14BDump(const char *Cmd) {
"Tries to autodetect cardtype, memory size defaults to SRI4K",
"hf 14b dump\n"
"hf 14b dump -f myfilename\n"
);
);
void *argtable[] = {
arg_param_begin,
@ -1080,7 +1087,7 @@ static int CmdHF14BDump(const char *Cmd) {
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
char *fptr = filename;
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
iso14b_card_select_t card;
@ -1635,11 +1642,11 @@ static int CmdHF14BAPDU(const char *Cmd) {
CLIParserFree(ctx);
PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s",
activate_field ? "sel" : "",
leave_signal_on ? " keep" : "",
decode_TLV ? " TLV" : "",
sprint_hex(data, datalen)
);
activate_field ? "sel" : "",
leave_signal_on ? " keep" : "",
decode_TLV ? " TLV" : "",
sprint_hex(data, datalen)
);
if (decode_APDU) {
APDUStruct apdu;
@ -1671,7 +1678,7 @@ static int CmdHF14BNdef(const char *Cmd) {
CLIParserInit(&ctx, "hf 14b ndef",
"Print NFC Data Exchange Format (NDEF)",
"hf 14b ndef"
);
);
void *argtable[] = {
arg_param_begin,
arg_param_end

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};
@ -903,13 +914,14 @@ 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."},
{NULL, NULL, 0, NULL}
{"help", CmdHelp, AlwaysAvailable, "This help."},
{"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}
};
int CmdHFFido(const char *Cmd) {

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)) {
PrintAndLogEx(SUCCESS, "Found default 3des key: ");
uint8_t keySwap[16];
memcpy(keySwap, SwapEndian64(key, 16, 8), 16);
ulc_print_3deskey(keySwap);
return PM3_SUCCESS;
}
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;
}
@ -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");
}
*/
actualTime += interval;
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

@ -299,7 +299,7 @@ static int cmd_hf_st_info(const char *Cmd) {
CLIParserInit(&ctx, "hf st info",
"Get info about ST25TA tag",
"hf st info"
);
);
void *argtable[] = {
arg_param_begin,
@ -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,21 +640,30 @@ 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 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 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
uint8_t step12[2] = {0xcd, 0x04}; //e-paper power off command
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 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
uint8_t step12[2] = {0xcd, 0x04}; // e-paper power off command
uint8_t step13[124] = {0xcd, 0x19, 121};
// uint8_t step13[2]={0xcd,0x0b}; //Judge whether the power supply is turned off successfully
// uint8_t step14[2]={0xcd,0x0c}; //The end of the transmission
// uint8_t step13[2]={0xcd,0x0b}; // Judge whether the power supply is turned off successfully
// uint8_t step14[2]={0xcd,0x0c}; // The end of the transmission
uint8_t rx[20];
uint16_t actrxlen[20], i = 0;
@ -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)) {
PrintAndLogEx(DEBUG, "DEBUG: Error - EM4305 preamble not found :: %zu", *startIdx);
return false;
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 PM3_ESOFT;
}
return PM3_EFAILED; // Error preamble found
}
return true;
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);
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()) {
res = doPreambleSearch(&idx);
if (res == PM3_SUCCESS)
break;
if (res == PM3_EFAILED)
found_err = true;
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);
if (detectPSK()) {
if (doPreambleSearch(&idx))
return setDemodBufferEM(word, idx);
psk1TOpsk2(DemodBuffer, DemodBufferLen);
if (doPreambleSearch(&idx))
return setDemodBufferEM(word, idx);
}
return PM3_ESOFT;
psk1TOpsk2(DemodBuffer, DemodBufferLen);
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)
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;
} else {
success = PM3_ESOFT; // If any error ensure fail is set so not to save invalid data
if (word != 0x00)
lock_bits = word;
data[14] = word;
status = EM4x05ReadWord_ext(15, pwd, usePwd, &word);
if (status != PM3_SUCCESS)
}
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
if (word != 0x00) // assume block 15 is the current lock block
lock_bits = word;
data[15] = word;
}
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) {
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' : ' ');
if ((needReadPwd) && (success != PM3_ESOFT)) {
data[addr] = BSWAP_32(pwd);
num_to_bytes(pwd, 4, bytes);
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,48 +1142,76 @@ 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);
}
struct {
uint32_t password;
uint32_t data;
uint8_t address;
uint8_t usepwd;
} PACKED payload;
if (protectOperation) { // set Protect Words
struct {
uint32_t password;
uint32_t data;
uint8_t usepwd;
} PACKED payload;
payload.password = pwd;
payload.data = data;
payload.address = addr;
payload.usepwd = usePwd;
payload.password = pwd;
payload.data = data;
payload.usepwd = usePwd;
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X_WRITEWORD, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_EM4X_WRITEWORD, &resp, 2000)) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT;
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;
uint8_t address;
uint8_t usepwd;
} PACKED payload;
payload.password = pwd;
payload.data = data;
payload.address = addr;
payload.usepwd = usePwd;
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X_WRITEWORD, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_EM4X_WRITEWORD, &resp, 2000)) {
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;
}
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;
}
}
//something went wrong
if (!(word & 0x8000))
return PM3_ESOFT;
// Loop dictionary
uint8_t *keyBlock = NULL;
if (found == false) {
printEM4x05ProtectionBits(word);
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;
}
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);
}
@ -219,7 +167,7 @@ static int CmdHIDWatch(const char *Cmd) {
"Enables HID compatible reader mode printing details.\n"
"By default, values are printed and logged until the button is pressed or another USB command is issued.\n",
"lf hid watch"
);
);
void *argtable[] = {
arg_param_begin,
@ -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
}
PrintAndLogEx(INFO, "Simulating HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo);
payload.longFMT = 1;
// 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;
}
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
}
PrintAndLogEx(INFO, "Preparing to clone HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo);
longid[0] = 1;
} 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
}
PrintAndLogEx(INFO, "Preparing to clone HID tag with ID: " _GREEN_("%x%08x"), hi, lo);
hi2 = 0;
// 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;
}
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 {
if (HIDPack(format_idx, &card, &packed) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
return PM3_ESOFT;
}
}
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,22 +396,22 @@ 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_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_lit0("v", "verbose", "verbose logging, show all tries"),
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
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -423,9 +420,10 @@ static int CmdHIDBrute(const char *Cmd) {
CLIGetStrWithReturn(ctx, 2, format, &formatLen);
format_idx = HIDFindCardFormat((char*) format);
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

@ -268,7 +268,7 @@ static int CmdKeriSim(const char *Cmd) {
CLIParserInit(&ctx, "lf keri sim",
"Enables simulation of KERI card with card number.",
"lf keri sim --id 112233"
);
);
void *argtable[] = {
arg_param_begin,

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,21 +105,23 @@ typedef struct {
uint32_t dw;
} t5555_tracedata_t;
typedef enum {
DEMOD_NRZ = 0x00,
DEMOD_PSK1 = 0x01,
DEMOD_PSK2 = 0x02,
DEMOD_PSK3 = 0x03,
DEMOD_FSK1 = 0x04,
DEMOD_FSK1a = 0x05,
DEMOD_FSK2 = 0x06,
DEMOD_FSK2a = 0x07,
DEMOD_FSK = 0xF0, //generic FSK (auto detect FCs)
DEMOD_ASK = 0x08,
DEMOD_BI = 0x10,
DEMOD_BIa = 0x18,
} t55xx_modulation;
typedef struct {
enum {
DEMOD_NRZ = 0x00,
DEMOD_PSK1 = 0x01,
DEMOD_PSK2 = 0x02,
DEMOD_PSK3 = 0x03,
DEMOD_FSK1 = 0x04,
DEMOD_FSK1a = 0x05,
DEMOD_FSK2 = 0x06,
DEMOD_FSK2a = 0x07,
DEMOD_FSK = 0xF0, //generic FSK (auto detect FCs)
DEMOD_ASK = 0x08,
DEMOD_BI = 0x10,
DEMOD_BIa = 0x18,
} modulation;
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,99 +580,89 @@ 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) {
// no crc, no annotations
uint8_t protocol = -1;
int slen = param_getstr(Cmd, cmdp, type, sizeof(type));
if (slen == 1) {
// validate type of output
if (strcmp(type, "iclass") == 0) protocol = ICLASS;
else if (strcmp(type, "14a") == 0) protocol = ISO_14443A;
else if (strcmp(type, "14b") == 0) protocol = ISO_14443B;
else if (strcmp(type, "topaz") == 0) protocol = TOPAZ;
else if (strcmp(type, "7816") == 0) protocol = ISO_7816_4;
else if (strcmp(type, "des") == 0) protocol = MFDES;
else if (strcmp(type, "legic") == 0) protocol = LEGIC;
else if (strcmp(type, "15") == 0) protocol = ISO_15693;
else if (strcmp(type, "felica") == 0) protocol = FELICA;
else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE;
else if (strcmp(type, "hitag1") == 0) protocol = PROTO_HITAG1;
else if (strcmp(type, "hitag2") == 0) protocol = PROTO_HITAG2;
else if (strcmp(type, "hitags") == 0) protocol = PROTO_HITAGS;
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;
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);
// validate type of output
if (strcmp(type, "iclass") == 0) protocol = ICLASS;
else if (strcmp(type, "14a") == 0) protocol = ISO_14443A;
else if (strcmp(type, "14b") == 0) protocol = ISO_14443B;
else if (strcmp(type, "topaz") == 0) protocol = TOPAZ;
else if (strcmp(type, "7816") == 0) protocol = ISO_7816_4;
else if (strcmp(type, "des") == 0) protocol = MFDES;
else if (strcmp(type, "legic") == 0) protocol = LEGIC;
else if (strcmp(type, "15") == 0) protocol = ISO_15693;
else if (strcmp(type, "felica") == 0) protocol = FELICA;
else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE;
else if (strcmp(type, "hitag1") == 0) protocol = PROTO_HITAG1;
else if (strcmp(type, "hitag2") == 0) protocol = PROTO_HITAG2;
else if (strcmp(type, "hitags") == 0) protocol = PROTO_HITAGS;
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;
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

@ -26,20 +26,20 @@
static int CmdHelp(const char *Cmd);
static void print_wiegand_code(wiegand_message_t *packed) {
const char* s = "Encoded wiegand: ";
const char *s = "Encoded wiegand: ";
if (packed->Top != 0) {
PrintAndLogEx(SUCCESS, "%s" _GREEN_("%X%08X%08X"),
s,
(uint32_t)packed->Top,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
s,
(uint32_t)packed->Top,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
} else {
PrintAndLogEx(SUCCESS, "%s" _YELLOW_("%X%08X"),
s,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
s,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
}
}
@ -49,7 +49,7 @@ int CmdWiegandList(const char *Cmd) {
CLIParserInit(&ctx, "wiegand info",
"List available wiegand formats",
"wiegand list"
);
);
void *argtable[] = {
arg_param_begin,
@ -68,7 +68,7 @@ int CmdWiegandEncode(const char *Cmd) {
CLIParserInit(&ctx, "wiegand encode",
"Encode wiegand formatted number to raw hex",
"wiegand encode -w H10301 --fc 101 --cn 1337"
);
);
void *argtable[] = {
arg_param_begin,
@ -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);
@ -91,7 +91,7 @@ int CmdWiegandEncode(const char *Cmd) {
int len = 0;
char format[16] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t*)format, sizeof(format), &len);
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)format, sizeof(format), &len);
CLIParserFree(ctx);
int idx = HIDFindCardFormat(format);
@ -118,7 +118,7 @@ int CmdWiegandDecode(const char *Cmd) {
CLIParserInit(&ctx, "wiegand decode",
"Decode raw hex to wiegand format",
"wiegand decode --raw 2006f623ae"
);
);
void *argtable[] = {
arg_param_begin,
@ -131,7 +131,7 @@ int CmdWiegandDecode(const char *Cmd) {
bool ignore_parity = arg_get_lit(ctx, 1);
int len = 0;
char hex[40] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t*)hex, sizeof(hex), &len);
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)hex, sizeof(hex), &len);
CLIParserFree(ctx);
if (len == 0) {

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;
@ -688,7 +717,7 @@ static int setCmdDeviceDebug (const char *Cmd)
showDeviceDebugState (prefShowOLD);
session.device_debug_level = newValue;
showDeviceDebugState (prefShowNEW);
preferences_save ();
preferences_save();
} else {
PrintAndLogEx(INFO,"nothing changed");
showDeviceDebugState (prefShowNone);
@ -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) {
controlWidget->show();
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,19 +653,23 @@ 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;
GraphStart += (refX - GraphStart) - ((refX - GraphStart) / factor);
if (refX > GraphStart) {
GraphStart += (refX - GraphStart) - ((refX - GraphStart) / factor);
}
}
} else { // Zoom out
if (GraphPixelsPerPoint >= 0.01 / factor) {
GraphPixelsPerPoint *= factor;
if (GraphStart >= ((refX - GraphStart) / factor) - (refX - GraphStart)) {
GraphStart -= ((refX - GraphStart) / factor) - (refX - GraphStart);
} else {
GraphStart = 0;
if (refX > GraphStart) {
if (GraphStart >= ((refX - GraphStart) / factor) - (refX - GraphStart)) {
GraphStart -= ((refX - GraphStart) / factor) - (refX - GraphStart);
} else {
GraphStart = 0;
}
}
}
}
@ -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,17 +803,33 @@ void Plot::keyPressEvent(QKeyEvent *event) {
switch (event->key()) {
case Qt::Key_Down:
if (event->modifiers() & Qt::ShiftModifier) {
Zoom(2, CursorBPos);
if (event->modifiers() & Qt::ControlModifier) {
Zoom(zoom_offset, CursorBPos);
} else {
Zoom(2, CursorBPos);
}
} else {
Zoom(2, CursorAPos);
if (event->modifiers() & Qt::ControlModifier) {
Zoom(zoom_offset, CursorAPos);
} else {
Zoom(2, CursorAPos);
}
}
break;
case Qt::Key_Up:
if (event->modifiers() & Qt::ShiftModifier) {
Zoom(0.5, CursorBPos);
if (event->modifiers() & Qt::ControlModifier) {
Zoom(1.0 / zoom_offset, CursorBPos);
} else {
Zoom(0.5, CursorBPos);
}
} else {
Zoom(0.5, CursorAPos);
if (event->modifiers() & Qt::ControlModifier) {
Zoom(1.0 / zoom_offset, CursorAPos);
} else {
Zoom(0.5, CursorAPos);
}
}
break;
@ -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,22 +245,26 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
#ifdef HAVE_READLINE
session.history_path = NULL;
if (searchHomeFilePath(&session.history_path, NULL, PROXHISTORY, true) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "No history will be recorded");
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;
} else {
# if defined(_WIN32)
// SetConsoleCtrlHandler((PHANDLER_ROUTINE)terminate_handler, true);
// SetConsoleCtrlHandler((PHANDLER_ROUTINE)terminate_handler, true);
# else
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_handler = &terminate_handler;
sigaction(SIGINT, &action, &old_action);
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_handler = &terminate_handler;
sigaction(SIGINT, &action, &old_action);
# endif
rl_catch_signals = 1;
rl_set_signals();
read_history(session.history_path);
rl_catch_signals = 1;
rl_set_signals();
read_history(session.history_path);
}
}
#endif
@ -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
) {
@ -581,7 +590,7 @@ LZ4_FORCE_INLINE int LZ4HC_compress_hashChain(
/* init */
*srcSizePtr = 0;
if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */
if (inputSize < LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
if (inputSize < LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
/* Main Loop */
while (ip <= mflimit) {
@ -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,8 +1558,11 @@ 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) */
@ -1526,8 +1571,8 @@ _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:

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